I thought I had found a shortcut. I thought that as long as the JSON object received resembled the structure of the TypeScript class, that I could just cast it to the TypeScript class.
This worked fine, until it didn't, and then I got this huge error in my face.
The problem
The problem started appearing when I defined a method in my TypeScript class. Naturally, this method is not available in the JSON Object, and no manner of Casting is going to make it magically appear there.You get something like:
ERROR TypeError: item.getItemPriceAsInteger is not a function
at ItemService.webpackJsonp.71.ItemService.updateItem (http://localhost.com/main.bundle.js:811:67)
at ItemSettingsComponent.webpackJsonp.183.ItemSettingsComponent.update (http://localhost.com/main.bundle.js:508:28)
at ItemSettingsComponent.webpackJsonp.183.ItemSettingsComponent.saveItem (http://localhost.com/main.bundle.js:480:14)
at Object.eval [as handleEvent] (ng:///AppModule/ItemSettingsComponent.ngfactory.js:1663:24)
at handleEvent (http://localhost.com/vendor.bundle.js:13600:138)
at callWithDebugContext (http://localhost.com/vendor.bundle.js:14892:42)
at Object.debugHandleEvent [as handleEvent] (http://localhost.com/vendor.bundle.js:14480:12)
at dispatchEvent (http://localhost.com/vendor.bundle.js:10500:21)
at http://localhost.com/vendor.bundle.js:12428:20
at SafeSubscriber.schedulerFn [as _next] (http://localhost.com/vendor.bundle.js:5549:36)
at ItemService.webpackJsonp.71.ItemService.updateItem (http://localhost.com/main.bundle.js:811:67)
at ItemSettingsComponent.webpackJsonp.183.ItemSettingsComponent.update (http://localhost.com/main.bundle.js:508:28)
at ItemSettingsComponent.webpackJsonp.183.ItemSettingsComponent.saveItem (http://localhost.com/main.bundle.js:480:14)
at Object.eval [as handleEvent] (ng:///AppModule/ItemSettingsComponent.ngfactory.js:1663:24)
at handleEvent (http://localhost.com/vendor.bundle.js:13600:138)
at callWithDebugContext (http://localhost.com/vendor.bundle.js:14892:42)
at Object.debugHandleEvent [as handleEvent] (http://localhost.com/vendor.bundle.js:14480:12)
at dispatchEvent (http://localhost.com/vendor.bundle.js:10500:21)
at http://localhost.com/vendor.bundle.js:12428:20
at SafeSubscriber.schedulerFn [as _next] (http://localhost.com/vendor.bundle.js:5549:36)
Solutions
There are several solutions available as described in [3, 4, 5].Chosen solution
I like the one provided in [6]. It uses TypeScript Decorators7. It can be installed as an npm package, according to [8].To anyone using Java, the solution provided has an uncanny resemblance to JPA annotated Entities or JAXB annotated classes.
I am going to go ahead and try this one out, and see how it works.
I'll provide an update, once I get some results.
References
- [1] Angular Docs - HTTP Client
- https://angular.io/docs/ts/latest/guide/server-communication.html
- [2] Writing a Search Result
- ng-book 2 - The Complete Book on Angular Nate Murray, Felipe Coury, Ari Lerner, Carlos Taborda
- [3] StackOverflow - How do I cast a JSON object to a typescript class
- https://stackoverflow.com/questions/22875636/how-do-i-cast-a-json-object-to-a-typescript-class
- [4] StackOverflow - Angular2 cast a json result to an interface
- https://stackoverflow.com/questions/34516332/angular2-cast-a-json-result-to-an-interface
- [5] Angular2 HTTP GET - Cast response into full object
- https://stackoverflow.com/questions/36014161/angular2-http-get-cast-response-into-full-object
- [6] Mark Galae - TypeScript Json Mapper
- http://cloudmark.github.io/Json-Mapping/
- [7] TypeScript - Decorators
- https://www.typescriptlang.org/docs/handbook/decorators.html
- Ninja Tips 2 - Make your JSON typed with TypeScript
- [8] npm - json-typescript-mapper
- https://www.npmjs.com/package/json-typescript-mapper
- http://blog.ninja-squad.com/2016/03/15/ninja-tips-2-type-your-json-with-typescript/
This comment has been removed by the author.
ReplyDeleteWe've found that casting doesn't work on nested objects including dates. Only the top level is actually cast. If your subproperty is defined as an object, its still being returned as a string.
ReplyDeleteThat's a shame. I thought long and hard about it, and currently I'm using simple Data Classes to contain the data, without any code. I don't like it.
DeletePerhaps I should just create a constructor in my dataClass that accepts a JSON Object.