Skip to content

bytefish/TypeScriptExperiments

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 

Repository files navigation

TypeScript Experiments

This repository contains various experiments with TypeScript.

/json-deserialization

If you have ever worked with JSON in an Angular application, you know that you cannot trust the deserialized results. JavaScript doesn't have Reflection, JSON doesn't have a data type for a Date and so... JSON.parse doesn't know that you want the incoming string value "2018-07-15T05:35:03.000Z" converted into a Date.

Say you have defined an interface Order as:

export interface Order {
    orderId?: number;
    orderNumber?: string;
    pickupDateTime?: Date
}

You call your Angular HttpClient with the generic HttpClient#get<T> overload:

this.httpClient
    .get<Order>(url, ...)
    .pipe(
        map((response: Order) => {
            // Work with the Response ...
        })
    );

Your Webservice responds with a totally valid JSON Order as:

{ 
    "orderId": 1,
    "orderNumber": "8472-423-14",
    "pickupDateTime":"2018-07-15T05:35:03.000Z"
}

And with a simple test, we can see, that the returned pickupDateTime is actually a string and not a Date:

describe('JSON.parse', () => {

    it('Should not parse string as Date', () => {
        
        // prepare
        const json = `
        { 
            "orderId": 1,
            "orderNumber": "8472-423-14",
            "pickupDateTime":"2018-07-15T05:35:03.000Z"
        }`;

        // act
        const verifyResult = JSON.parse(json) as Order;

        // verify
        const isTypeOfString = typeof verifyResult.pickupDateTime === "string";
        const isInstanceOfDate = verifyResult.pickupDateTime instanceof Date;
        
        deepStrictEqual(isTypeOfString, true);
        deepStrictEqual(isInstanceOfDate, false);
    }); 
    
});

In this example we will take a look at providing a set of decorators (@JsonProperty, @JsonType, ...) to decorate classes and deserialize the JSON into the correct types. It will look like this:

export class Order {

    @JsonProperty("orderId")
    orderId?: number;

    @JsonProperty("orderNumber")
    orderNumber?: string;

    @JsonProperty("pickupDateTime")
    @JsonType(Date)
    pickupDateTime?: Date;
}

And with a simple test, we will see the correct types on our deserialized object:

describe('deserialize', () => {

    it('Decorated Order should parse Date', () => {
        // prepare        
        const json = `
        { 
            "orderId": 1,
            "orderNumber": "8472-423-14",
            "pickupDateTime":"2018-07-15T05:35:03.000Z"
        }`;

        // act
        const verifyResult: Order = deserialize<Order>(json, Order);

        // verify
        const isTypeOfObject = typeof verifyResult.pickupDateTime === "object";
        const isInstanceOfDate = verifyResult.pickupDateTime instanceof Date;
        
        deepStrictEqual(isTypeOfObject, true);
        deepStrictEqual(isInstanceOfDate, true);
    }); 
});

That enables us a bit more type-safety, when deserializing incoming JSON data.

About

Experiments with TypeScript

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published