Sven do you think that it is worth to create a new section with the
xample and the solution in the book?

On Sun, Sep 24, 2017 at 11:05 AM, Sven Van Caekenberghe <s...@stfx.eu> wrote:
> Hi Juraj,
>
> This would be a simpler form of the type/class tags that are often used in 
> JSON encoding. Since there are many ways to do this, there cannot be one 
> solution. NeoJSON mapping was not designed to cover these cases. Nor is JSON 
> meant to do this. STON is one (rather elegant if I may say so) answer to this 
> problem. Your example would be encoded as
>
> [
>   PngAttachement { #url:'http://example.com/random-name.txt', 
> #fileName:'chapter-one.txt' },
>   TxtAttachement { #url:'http://example.com/random-name.png', 
> #fileName:'image.png' }
> ]
>
> Still, the question of how to do this kind of dynamic decoding is an 
> interesting challenge. Please update to the following commits:
>
> ===
> Name: Neo-JSON-Core-SvenVanCaekenberghe.44
> Author: SvenVanCaekenberghe
> Time: 22 September 2017, 3:24:51.679449 pm
> UUID: f1ebeade-2816-0d00-a04c-ae370e598362
> Ancestors: Neo-JSON-Core-SvenVanCaekenberghe.42
>
> Implement some missing code in NeoJSONCustomMapping (the writing part of 
> #listOfElementSchema: #listOfType:andElementSchema: #mapWithValueSchema:)
>
> Add NeoJSONStreamingWriter>>#writeElementAs:
>
> Add NeoJSONMappingTests>>#testDynamicTyping as an example
> ===
> Name: Neo-JSON-Tests-SvenVanCaekenberghe.41
> Author: SvenVanCaekenberghe
> Time: 22 September 2017, 3:25:09.881494 pm
> UUID: a9a900e0-2816-0d00-a04d-a6fb0e598362
> Ancestors: Neo-JSON-Tests-SvenVanCaekenberghe.39
>
> Implement some missing code in NeoJSONCustomMapping (the writing part of 
> #listOfElementSchema: #listOfType:andElementSchema: #mapWithValueSchema:)
>
> Add NeoJSONStreamingWriter>>#writeElementAs:
>
> Add NeoJSONMappingTests>>#testDynamicTyping as an example
> ===
>
> Now you can do as follows:
>
> NeoJSONMappingTests>>#testDynamicTyping
>   | data customMapping json result |
>   data := Array with: #foo->1 with: #(foo 2).
>   "The idea is to map a key value combination as either a classic association 
> or a simple pair,
>    using key & value properties as well as a type property to distinguish 
> between the two"
>   customMapping := [ :mapper |
>     mapper
>       for: #AssocOrPair customDo: [ :mapping |
>         mapping
>           encoder: [ :x |
>             x isArray
>               ifTrue: [ { #type->#pair. #key->x first. #value->x second } 
> asDictionary ]
>               ifFalse: [ { #type->#assoc. #key->x key. #value->x value } 
> asDictionary ] ];
>           decoder: [ :x |
>             (x at: #type) = #pair
>               ifTrue: [ Array with: (x at: #key) with: (x at: #value) ]
>               ifFalse: [ (x at: #key) -> (x at: #value)] ] ];
>       for: #ArrayOfAssocOrPair customDo: [ :mapping |
>         mapping listOfType: Array andElementSchema: #AssocOrPair ];
>       yourself ].
>   json := String streamContents: [ :out |
>     (customMapping value: (NeoJSONWriter on: out)) nextPut: data as: 
> #ArrayOfAssocOrPair ].
>   result := (customMapping value: (NeoJSONReader on: json readStream)) 
> nextAs: #ArrayOfAssocOrPair.
>   self assert: result equals: data
>
> Everything is virtual (not implemented as methods on actual classes) which 
> makes the example self contained and non intrusive, but not very elegant, nor 
> object oriented or extendable. Also, it is not as efficient as NeoJSON 
> mapping was designed for, since it creates intermediate structures.
>
> HTH,
>
> Sven
>
>> On 21 Sep 2017, at 22:07, Juraj Kubelka <juraj.kube...@icloud.com> wrote:
>>
>> Hi,
>>
>> By studying the NeoJSON book chapter (Pharo Enterprise), I do not understand 
>> how to modify the following example:
>>
>> -=-=-=-=-=-=-=-
>> "Let us say that we have an Attachment class..."
>>
>> Object subclass: #Attachment
>>       instanceVariableNames: 'url fileName'
>>       classVariableNames: ''
>>       package: 'NeoJSON-Use-Case'.
>>
>> "...with url: and fileName: methods."
>> Attachment compile: 'url: anObject', String cr, String tab, 'url := 
>> anObject' classified: 'accessing'.
>> Attachment compile: 'fileName: anObject', String cr, String tab, 'fileName 
>> := anObject' classified: 'accessing'.
>>
>> "Let's create a collection of two instances:"
>> collectionOne := {
>>       Attachment new
>>               url: 'http://example.com/random-name.txt' asZnUrl;
>>               fileName: 'chapter-one.txt'
>>               yourself.
>>       Attachment new
>>               url: 'http://example.com/random-name.png' asZnUrl;
>>               fileName: 'image.png';
>>               yourself.
>> }.
>>
>> "And let's map it to a JSON structure:"
>> String streamContents: [ :aStream |
>>       (NeoJSONWriter on: aStream)
>>               for: #CollectionOfAttachments customDo: [ :mapping |
>>                       mapping listOfElementSchema: Attachment ];
>>               mapAllInstVarsFor: Attachment;
>>               for: ZnUrl customDo: [ :mapping |
>>                       mapping encoder: [ :aZnUrl |
>>                               aZnUrl asString ] ];
>>               nextPut: collectionOne as: #CollectionOfAttachments.
>> ].
>>
>> "And read the JSON structure:"
>> (NeoJSONReader on: 
>> '[{"url":"http://example.com/random-name.txt","fileName":"chapter-one.txt"},{"url":"http://example.com/random-name.png","fileName":"image.png"}]'
>>  readStream)
>>       for: #CollectionOfAttachments customDo: [ :mapping |
>>                       mapping listOfElementSchema: Attachment ];
>>       for: Attachment do: [ :mapping |
>>               mapping mapInstVar: 'fileName'.
>>               (mapping mapInstVar: 'url') valueSchema: ZnUrl ];
>>       for: ZnUrl customDo: [ :mapping |
>>               mapping decoder: [ :string |
>>                       string asZnUrl ] ];
>>       nextAs: #CollectionOfAttachments.
>>
>> "======================="
>> “The previous example works perfectly, including the ZnUrl mapping (notice 
>> that url variables have ZnUrl instances).
>>
>> Now, let's say that we want to distinguish PNG and TXT attachments.
>> For that reason we will create two Attachment subclasses..."
>>
>> Attachment subclass: #PngAttachment
>>       instanceVariableNames: ''
>>       classVariableNames: ''
>>       package: 'NeoJSON-Use-Case'.
>>
>> Attachment subclass: #TxtAttachment
>>       instanceVariableNames: ''
>>       classVariableNames: ''
>>       package: 'NeoJSON-Use-Case'.
>>
>> "...with type methods that might be used in a new JSON structure:"
>> PngAttachment compile: 'type', String cr, String tab, '^ ''png''' 
>> classified: 'accessing'.
>> TxtAttachment compile: 'type', String cr, String tab, '^ ''txt''' 
>> classified: 'accessing'.
>>
>> "Let's create a collection with the PNG and TXT instances:"
>> collectionTwo := {
>>       TxtAttachment new
>>               url: 'http://example.com/random-name.txt' asZnUrl;
>>               fileName: 'chapter-one.txt'
>>               yourself.
>>       PngAttachment new
>>               url: 'http://example.com/random-name.png' asZnUrl;
>>               fileName: 'image.png';
>>               yourself.
>> }.
>>
>> "How can I modify NeoJSONWriter and NeoJSONReader mappings?
>>
>> The JSON structure should (ideally) looks like this:"
>>
>> '[
>>       
>> {“type”:”txt”,"url":"http://example.com/random-name.txt","fileName":"chapter-one.txt”},
>>       
>> {“type”:”png”,"url":"http://example.com/random-name.png","fileName":"image.png”}
>> ]'
>> -=-=-=-=-=-=-=-
>>
>> I would like to keep the mapping isolated (without defining neoJsonOn: 
>> methods).
>>
>> Thank you!
>> Juraj
>>
>
>

Reply via email to