JSON to TypeScript class instance? [duplicate] JSON to TypeScript class instance? [duplicate] json json

JSON to TypeScript class instance? [duplicate]


This question is quite broad, so I'm going to give a couple of solutions.

Solution 1: Helper Method

Here's an example of using a Helper Method that you could change to fit your needs:

class SerializationHelper {    static toInstance<T>(obj: T, json: string) : T {        var jsonObj = JSON.parse(json);        if (typeof obj["fromJSON"] === "function") {            obj["fromJSON"](jsonObj);        }        else {            for (var propName in jsonObj) {                obj[propName] = jsonObj[propName]            }        }        return obj;    }}

Then using it:

var json = '{"name": "John Doe"}',    foo = SerializationHelper.toInstance(new Foo(), json);foo.GetName() === "John Doe";

Advanced Deserialization

This could also allow for some custom deserialization by adding your own fromJSON method to the class (this works well with how JSON.stringify already uses the toJSON method, as will be shown):

interface IFooSerialized {    nameSomethingElse: string;}class Foo {  name: string;  GetName(): string { return this.name }  toJSON(): IFooSerialized {      return {          nameSomethingElse: this.name      };  }  fromJSON(obj: IFooSerialized) {        this.name = obj.nameSomethingElse;  }}

Then using it:

var foo1 = new Foo();foo1.name = "John Doe";var json = JSON.stringify(foo1);json === '{"nameSomethingElse":"John Doe"}';var foo2 = SerializationHelper.toInstance(new Foo(), json);foo2.GetName() === "John Doe";

Solution 2: Base Class

Another way you could do this is by creating your own base class:

class Serializable {    fillFromJSON(json: string) {        var jsonObj = JSON.parse(json);        for (var propName in jsonObj) {            this[propName] = jsonObj[propName]        }    }}class Foo extends Serializable {    name: string;    GetName(): string { return this.name }}

Then using it:

var foo = new Foo();foo.fillFromJSON(json);

There's too many different ways to implement a custom deserialization using a base class so I'll leave that up to how you want it.


You can now use Object.assign(target, ...sources). Following your example, you could use it like this:

class Foo {  name: string;  getName(): string { return this.name };}let fooJson: string = '{"name": "John Doe"}';let foo: Foo = Object.assign(new Foo(), JSON.parse(fooJson));console.log(foo.getName()); //returns John Doe

Object.assign is part of ECMAScript 2015 and is currently available in most modern browsers.


What is actually the most robust and elegant automated solution for deserializing JSON to TypeScript runtime class instances?

Using property decorators with ReflectDecorators to record runtime-accessible type information that can be used during a deserialization process provides a surprisingly clean and widely adaptable approach, that also fits into existing code beautifully. It is also fully automatable, and works for nested objects as well.

An implementation of this idea is TypedJSON, which I created precisely for this task:

@JsonObjectclass Foo {    @JsonMember    name: string;    getName(): string { return this.name };}
var foo = TypedJSON.parse('{"name": "John Doe"}', Foo);foo instanceof Foo; // truefoo.getName(); // "John Doe"