Hi Sven,

> On Dec 30, 2015, at 12:51 PM, Sven Van Caekenberghe <s...@stfx.eu> wrote:
> 
> I added a new feature:

Thank you for this new feature!

> From the unit test, this allows you to do as follows:
> 
> self
>  assert: ((NeoJSONReader on: 'null' readStream)
>             mapInstVarsFor: Point;
>             for: Point do: [ :mapping | mapping allowNil ];
>             nextAs: Point)
>  equals: nil.
> 
> self
>  assert: ((NeoJSONReader on: '[ { "x" : 1, "y" : 2 }, null, { "x" : 3, "y" : 
> -1 } ]' readStream)
>             mapInstVarsFor: Point;
>             for: Point do: [ :mapping | mapping allowNil ];
>             for: #ArrayOfPoints customDo: [ :mapping | mapping 
> listOfElementSchema: Point ];
>             nextAs: #ArrayOfPoints)
>  equals: { 1 @ 2. nil. 3 @ -1 }.
> 
> I decided to make this a per mapping option, not a per reader option.

Maybe there should be an ensureNotNil option too, which sets allowNil to false?
This allows for changing it back to the default mode when reusing the same 
reader.

I tried making this a per _property mapping_ option, but it became a bit of a 
hack so I stopped doing that.

> No, that would not help ;-)
> 
> The two approaches are fundamentally different: either you accept anything 
> that is present (dynamic mode), returning lists (Arrays) and maps 
> (Dictionaries), or you accept a schema that is predefined (static mode).
> 
>>> When you use mappings and #nextAs: it tries to map a static type structure 
>>> on what is coming in. As such it is not really prepared for dynamic 
>>> surprises like objects being replaced by null.
>> 
>> Yes, in the general case, once you’ve sent #nextAs: to the reader with your 
>> value schema, you’re “stuck” with that exact schema.
>> 
>> While working on the bindings for the GitHub API, there are some JSON 
>> representations which send a “type” field (e.g. “type” : “commit”).
>> I would like it to be possible to change the class schema to that of a 
>> subclass of the original class when detecting a combination of fields.
>> 
>> That is, I specify a combination of fields, and if any is present, then 
>> change the class of the current object to a subclass. By specifying 
>> combinations of fields, you don't rely on the order in which they appear in 
>> the JSON.
>> 
>> Maybe in this way it is possible to accomplish without giving up the nice 
>> property of NeoJSON not making intermediate structures? Sounds tough to do 
>> without turning it into a hack though..
> 
> I know what you mean, there are 2 common approaches (some would call it a 
> wrong way to use JSON, but that is another discussion):
> 
>  { "type":"Point", "x":1, "y":2 }
> 
> or
> 
>  { "type":"Point", "value": {"x":1, "y":2} }
> 
> (Type could be class, or whatever). 
> 
> The first case is bad, you have to read everything before you can make a 
> decision, which IMO kills the advantage of mapping while trying to avoid 
> intermediate structures (i.e. you could do the mapping yourself afterwards).
> 
> The second case is a bit better, but not much. Both top level elements could 
> have switched place, in which case you already have to read the value, not 
> knowing what to map it to.

Exactly, this is what I meant.

> You could try experimenting with Custom mappings, they allow arbitrary 
> conversions, but I doubt if you could really prevent intermediate structure 
> creation. But maybe I just don't see it right, and it is possible after all.

One could perhaps use adoptInstance:, based on some conditions (e.g. “if the 
json contains this combination of keys”, “if the type field has the value 
“commit””).

But on the other hand this solution would make NeoJSON less simple, and the 
simplicity of the library is a very nice property. It would be stupid to throw 
that property away for a solution that doesn't even cover all of the cases.

> If the returned JSON is highly dynamic and variable, I would just use dynamic 
> mode and then in a second pass convert the maps/lists to domain objects 
> myself. Or someone should write a generic maps/lists to domain model objects 
> mapper (independent of JSON).

Yes this might be the best solution in this case.

Best wishes for 2016 :),

Skip

Reply via email to