TypeScript properties and JSON.stringify
Posted on 2015-04-22
TypeScript supports ECMA 5.1’s properties
quite well but it seems it doesn’t play well with
This entire blog post talks about how I ended up mapping JSON from our REST API into our project’s TypeScript classes. The first problem when doing that was that we wanted classes in our code with all the functions and helpers and static properties and whatnot. So we defined them as classes with TypeScript.
But when the JSON came back, it contained properties that had the same name as some functions, so the function would be overriden by any basic mapping code.
So I set out to create a base class that was more mapping aware.
The result is here: https://gist.github.com/cdroulers/479c966506c92ed1fac0
The mapping magic happens in the constructor. The
data parameter is the JSON (or undefined when not mapping). It iterates through every property of the data,
automatically ignoring functions of the class. Then, there are three options:
- If the property found has a mapping function in the
_mapOptionsobject, it calls that function to map the sub-entity. So if you have a tree of classes, they can easily be mapped
- If the property found has a mapping name in the
PropertyNames, then the property is set on the object as the mapped property name.
- If the property is not explicitely ignored, then it is simply mapped on the object.
Option 2 is where the magic happens for Properties. Say you have a property like this one:
When the JSON comes back from an API call with the
Name property set to “Roger”, you don’t necessarily want it to go through the setter. So in the
you pass the following:
Then, the JSON maps to private fields and no accessors are used and we have clean and pretty properties on our classes.
Then when I wanted to serialize the class back into JSON, the properties did NOT show up! I was very confused. So I looked into how TypeScript generates the property
and found it it defines it on the prototype of the class instead of on the object. The behaviour can be seen in
Class1 is what TypeScript would generate for our class higher up the post.
serialise properties defined on the prototype and I was a bit annoyed.
I asked the question on Stack Overflow
and got responses basically indicating that it was standard behaviour and a few workarounds. I set out to work around it using the
toJSON function. Since I keep the
_mapOptions as a private member, I used those to reverse map property names and ignore certain properties.
toJSON is automatically called by
any framework that uses that to serialise your classes (AngularJS does!) will get a proper object to serialise.
This is the best way I found to handle mapping to and from JSON with TypeScript. Any other suggestions?comments powered by Disqus