On 07/06/2018 17:21, Tim Mackinnon wrote: > Hi - is there something I can read/study to get a bit more familiar with Json > mapping? I have read the Pharo enterprise book (chapter 8). > > I’ve been using NeoJSONObject but then it occurred to me that maybe I could > map better domain objects directly and simplify things. However it seems that > the intent of mapping is just for simple things like an array of points - > whereas if I have 15 different domain objects (albeit with a type key), then > I’m wondering if I should just wrap json nodes on usage? > > In fact I’m wondering what the point of mapping is if it’s so simple - or > maybe I’m missing an important concept? If your objects just hold data, then you can get very far with NeoJSONObject, but if you want to do more, you can get pretty extensible mappings with the use of the valueSchema: option in the mapper.
For instance, to write a TsOrder (a model of an purchase order) I configured the mapper this way: mapper for: TsOrder do: [ :mapping | mapping mapAccessors: #(id). (mapping mapAccessor: #date) valueSchema: Date. (mapping mapAccessor: #edd) valueSchema: #NamedModel. (mapping mapAccessor: #provider) valueSchema: #NamedModel. (mapping mapAccessor: #status) valueSchema: #NamedModel. (mapping mapAccessor: #customerCode). (mapping mapAccessor: #totalOriginalPrice to: 'total') valueSchema: #monetary. ]. mapper for: Date customDo: [ :mapping | mapping encoder: [ :date | date ddmmyyyy ] ]. mapper for: #monetary customDo: [ :mapping | mapping encoder: [ :price | price printShowingDecimalPlaces: 2 ] ]. mapper for: DateAndTime customDo: [ :mapping | mapping decoder: [ :string | DateAndTime fromString: string ]. ]. mapper for: #NamedModel customDo: [ :mapping | mapping encoder: [ :persona | persona displayString ] ]. For decoding it might be trickier, because you might need more objects other than just deserializing from JSON, e.g. to avoid instantiating twice the same domain object, or if you need to lookup an entity in the database by ID, and then you need access to the database, etc. Throughout my journey of developing a few JSON-REST APIs I started using the NeoJSON approach, then JsonObject and then WAJsonCanvas. I found myself more confortable writing JSON with the latter (I like the canvas approach of Seaside) and instantiating NeoJSONObject/JsonObject and building my business objects from these cherry picking what I needed. What NeoJSON offers as a "differentiator" is that it is stream based, so there is no need to have intermediate "structures" (it is, dictionaries), and the mappers are orthogonal to the objects (unless you use the default class side #neoJsonMapping:) WAJsonCanvas offers stream based writing, but there are no mappings, but if you always serialize a proper hierarchy of renderJsonOn: implementors could prove to be effective, in particular if you have to build your objects manually from a JSON stream. Regards, -- Esteban A. Maringolo