[Pharo-users] NeoJSON mapping question

Sven Van Caekenberghe sven at stfx.eu
Tue Feb 26 15:56:30 EST 2019


Bruno,

What about the following ?

json := '{ "id" : 1, "level1" : { "level2" : { "name" : "foo" } } }'.

In the JSON above there is a nesting level1.level2.name that you want to skip over.

One solution would be:

NeoJSONReader new
  on: json readStream;
  for: #Foo customDo: [ :mapping |
    mapping decoder: [ :x |
	  (x at: #id) -> (((x at: #level1) at: #level2) at: #name) ] ];
  nextAs: #Foo.

The returned type is an Association, but it could be a domain object. #Foo is just an identifier. The disadvantage is that anything deeper is not mapped, but comes in as a plain dictionary, in a sense defeating the concept of mapping (but for leaf like structures this might be what you want).

Alternatively, if you use NeoJSONObject instead of Dictionary, it becomes easier to access a nested path:

NeoJSONReader new
  on: json readStream;
  mapClass: NeoJSONObject;
  for: #Foo customDo: [ :mapping |
    mapping decoder: [ :x |
	  (x at: #id) -> (x atPath: #(level1 level2 name)) ] ];
  nextAs: #Foo.

HTH,

Sven

PS: Note also that mappings can live on the class side (where they are global), but also inside specific NeoJSONReader instances (where they are local), like here.

> On 26 Feb 2019, at 03:50, BrunoBB <smalltalk at adinet.com.uy> wrote:
> 
> Hi,
> 
> The following implementation do what i want without the need to create a
> class for each level of the JSON, however i really dislike my solution.
> neoJsonMapping: mapper "class side"
> 	"Map the receiver to a json with <NeoJSONObjectMapping> <mapper>"
> 	mapper for: self do: [ :mapping |
> 		(mapping mapProperty: 'booking' getter: [:obj | obj locator] setter: [
> :obj :value | obj setLocator: value]) valueSchema: self.
> 	].
> 
> 	mapper for: self do: [ :mapping |
> 		mapping mapProperty: '@locator' getter: [:obj | obj locator] setter: [
> :obj :value | obj locator: value]
> 	]
> 
> The first part map 'booking' property to the class locator inst var. The
> second part have access to the "second json level" and the value i'm looking
> for.
> 
> But setLocator: anObject is the ugly thing :(
> setLocator: anObject
> 	(anObject class == PmsJsonInput) ifTrue: [^locator := anObject locator].
> 	locator := anObject
> 
> I'm sure there must be another way to do this.
> 
> regards,
> bruno
> 
> 
> 
> --
> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
> 




More information about the Pharo-users mailing list