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 >> > >