That you very much for your input and a great library. I will use a variation of the second solution.
Hi Milan,
I understand your question, but currently there is no out of the box support for class/type mapping using maps like in your example (there are other variation too, like class/type properties, nested or not). The reason is that this involves schema checking which I didn't want to do due to the added complexity and lack of standardization (this is intentionally outside the JSON spec proper).
On 20 Aug 2012, at 14:02, Milan Mimica <milan.mimica@gmail.com> wrote:
> Hello
>
> I have obtained a json from a HTTP response which looks like:
> {"login":{"verified":true,"authCookie":"2eb62b41-5156-4056-9b5d-9252b52c93a2"}}
>
> I want to map this into a Smalltalk class LoginResponse which has two instance variables: verified and authCookie. So I need the mapper to ignore the root property name "login". I think that is a quite common use case. How can it be done?
>
>
> --
> Milan Mimica
> http://sparklet.sf.net
You have 2 options:
- either use generic parsing and do the conversions and schema checking after the parsing (which is what most JSON parser make you do anyway)
NeoJSONReader fromString: '{"login":{"verified":true,"authCookie":"2eb62b41-5156-4056-9b5d-9252b52c93a2"}}'.
- write a custom mapping that looks a bit like a hack
(NeoJSONReader on: '{"login":{"verified":true,"authCookie":"2eb62b41-5156-4056-9b5d-9252b52c93a2"}}' readStream)
� � � � for: #LoginResponseWrapper customDo: [ :mapping |
� � � � � � � � mapping reader: [ :jsonReader | | result |
� � � � � � � � � � � � result := nil.
� � � � � � � � � � � � jsonReader parseMapKeysDo: [ :key |
� � � � � � � � � � � � � � � � key = #login
� � � � � � � � � � � � � � � � � � � � ifTrue: [ result := jsonReader next ] ].
� � � � � � � � � � � � result ] ];
� � � � nextAs: #LoginResponseWrapper
the above example will go into the login element if it is present and return a dictionary.
To make it return your class, this should do the trick
(NeoJSONReader on: '{"login":{"verified":true,"authCookie":"2eb62b41-5156-4056-9b5d-9252b52c93a2"}}' readStream)
� � � � mapInstVarsFor: LoginResponse;
� � � � for: #LoginResponseWrapper customDo: [ :mapping |
� � � � � � � � mapping reader: [ :jsonReader | | result |
� � � � � � � � � � � � result := nil.
� � � � � � � � � � � � jsonReader parseMapKeysDo: [ :key |
� � � � � � � � � � � � � � � � key = #login
� � � � � � � � � � � � � � � � � � � � ifTrue: [ result := jsonReader nextAs: LoginResponse ] ].
� � � � � � � � � � � � result ] ];
� � � � nextAs: #LoginResponseWrapper
I can image a more general purpose LoginResponseWrapper that maps multiple types at once.
HTH,
Sven
--
Sven Van Caekenberghe
http://stfx.eu
Smalltalk is the Red Pill