9

I have some JSON containing anonymous objects coming to my client-side. Is there some built-in mechanism or external library for converting these anonymous objects into strongly-typed TypeScript objects? Is there something like AutoMapper for doing this?

My objects are complex types, with complex types as properties.

Ryan Shripat
  • 5,574
  • 6
  • 49
  • 77
  • You need to write the mapper yourself (or download code from the net) -- for example, most libraries will have a ``mixin`` function that allows you to mixin properties from one object to another. Then just cast your strongly-typed object into ``any`` and pass it into the mapper with your JSON object. The strongly-typed object will be filled just like any plain old JavaScript object. – Stephen Chung Sep 01 '13 at 08:07

3 Answers3

9

Get some sample data and place it in a .ts file:

var people = [
    {
        "name": "bob", "height": 150, "pets": [{ "name": "spot", "species": "dog" }]
    },
    {
        "name": "jane", "height": 142, "pets": [{ "name": "lucy", "species": "cat" }]
    }
];

Run tsc --declaration yourFile.ts

Now you'll have yourFile.d.ts:

declare var people: {
    "name": string;
    "height": number;
    "pets": {
        "name": string;
        "species": string;
    }[];
}[];

Replace declare var people: with interface Person, remove the trailing [], and (optionally) remove the quotes:

interface Person {
    name: string;
    height: number;
    pets: {
        name: string;
        species: string;
    }[];
}
Ryan Cavanaugh
  • 209,514
  • 56
  • 272
  • 235
  • This is nice, but I was looking for something that could do it for me on the fly. – Ryan Shripat Aug 29 '13 at 21:15
  • @RyanShripat when you say "on the fly" do you mean automatically generate the file, or do it at runtime? – Fenton Sep 01 '13 at 06:49
  • I want to be able to say: var people = [...] /* anonymous JSON object */; then say: People p = ConvertAnonToStrong(people);, with errors at run-time if the conversion doesn't work. – Ryan Shripat Sep 02 '13 at 11:27
  • 3
    "with errors at run-time if the conversion doesn't work" - TypeScript is a compile time only language that produces pure JavaScript, so it can't provide runtime type constraints. – serg10 Sep 03 '13 at 07:43
3

Recently I created an AutoMapper implementation in TypeScript / JavaScript exactly for this scenario. I have put the code at GitHub (AutoMapperTS). You can also use the library directly using the automapper-ts NPM package or automapper-ts Bower package.

The library is almost fully documented. Furthermore, quite a lot of Jasmine unit tests are already available (code coverage is over 90%). They should provide you with some explanation of needed.

I hope this library suits your needs. Should you have any questions and/or remarks, please don't hesitate contacting me!

Happy coding!

DotBert
  • 1,262
  • 2
  • 16
  • 29
1

I was looking for an easy way to convert json data from a web service to an interface too. Didn't found what I need but here is my solution. Noticed that I added a "Pet" interface and added another pet to your json. Also had to specify the anonymous object as "any". You can cut/paste this to TypeScript playground (http://www.typescriptlang.org/play/index.html) to see the results. Hope this helps.

let header = document.createElement("div");
header.textContent = "Test";
document.body.appendChild(header);

var people:any = [
    {
        "name": "bob", "height": 150, "pets": [{ "name": "spot", "species": "dog" }, {"name" : "violet", "species": "shark"}]
    },
    {
        "name": "jane", "height": 142, "pets": [{ "name": "lucy", "species": "cat" }]
    }
];

interface Pet {
    name: string;
    species: string;
}
interface Person {
    name: string;
    height: number;
    pets: Array<Pet>
}

class Foo {
    convertToObject = (person: Person) => person;
}


var person = new Foo().convertToObject(people[0]);

let div = document.createElement("div");
div.textContent = `hey ${person.name} I see you have ${person.pets.length} pet`;
document.body.appendChild(div);
howardlo
  • 1,401
  • 1
  • 15
  • 20