WAJsonCanvas

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

WAJsonCanvas

Esteban A. Maringolo
I migrated to Seaside 3.1, and I had a mix of NeoJSON and old style
#jsonOn: implementations.

By fixing the old style #jsonOn: to work with a WAJsonCanvas, I found
I don't have a way to create an array definition specifying each
element.

It is, the implementation delegates the rendering to the Collection
class, but I can't control it to do it manually:


However, I implemented an #element: selector in WAJsonCanvas as follows:
WAJsonCanvas>>#element: aValueObject
  ^ (self brush: (WAJsonElementBrush new)) with: aValueObject

And then I could do:

WAJsonCanvas builder render: [ :json |
  json array: [
     WADocument  allSubclasses do:[:each |
        json element: [
           json object: [ json key: 'name' value: each name ]
        ]
     ]
   ]
]

which generates the following output:
[{"name": "WAXmlDocument"}, {"name": "WAJsonDocument"}, {"name":
"WAHtmlDocument"}, {"name": "WAUnescapedDocument"}, {"name":
"WAPrettyPrintedDocument"}]

Without using the #element: brush all the elements aren't comma
separated. Maybe there is another way of doing it, delegating it to
the array brush.

Is this okay? Can this be added to Seaside-JSON-Core?

Regards,

Esteban A. Maringolo
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: WAJsonCanvas

Johan Brichau-2
Hi Esteban,

I don't think you need the extra #element method.
How about the following:

        WAJsonCanvas builder render: [ :json |
                json array: [
                        WADocument  allSubclasses do:[:each |
                                json value: [  json object: [ json key: 'name' value: each name ] ]]]

this produces:

        '[{"name": "WAXmlDocument"}, {"name": "WAJsonDocument"}, {"name": "WAHtmlDocument"}, {"name": "WAUnescapedDocument"}, {"name": "WAPrettyPrintedDocument"}]'

But this example makes me think... I would actually want to write it as follows:

        WAJsonCanvas builder render: [ :json |
                json array: [
                        WADocument  allSubclasses do:[:each |
                                json object: [ json key: 'name' value: each name ]]]]

i.e. without the #value: message. I would expect the canvas to put a comma in between different objects. An 'object' is actually a 'value' in the json syntax.
It might make sense.

Johan


On 21 Feb 2014, at 16:23, Esteban A. Maringolo <[hidden email]> wrote:

> I migrated to Seaside 3.1, and I had a mix of NeoJSON and old style
> #jsonOn: implementations.
>
> By fixing the old style #jsonOn: to work with a WAJsonCanvas, I found
> I don't have a way to create an array definition specifying each
> element.
>
> It is, the implementation delegates the rendering to the Collection
> class, but I can't control it to do it manually:
>
>
> However, I implemented an #element: selector in WAJsonCanvas as follows:
> WAJsonCanvas>>#element: aValueObject
>  ^ (self brush: (WAJsonElementBrush new)) with: aValueObject
>
> And then I could do:
>
> WAJsonCanvas builder render: [ :json |
>  json array: [
>     WADocument  allSubclasses do:[:each |
>        json element: [
>           json object: [ json key: 'name' value: each name ]
>        ]
>     ]
>   ]
> ]
>
> which generates the following output:
> [{"name": "WAXmlDocument"}, {"name": "WAJsonDocument"}, {"name":
> "WAHtmlDocument"}, {"name": "WAUnescapedDocument"}, {"name":
> "WAPrettyPrintedDocument"}]
>
> Without using the #element: brush all the elements aren't comma
> separated. Maybe there is another way of doing it, delegating it to
> the array brush.
>
> Is this okay? Can this be added to Seaside-JSON-Core?
>
> Regards,
>
> Esteban A. Maringolo
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: WAJsonCanvas

Philippe Marschall
On Sat, Feb 22, 2014 at 9:15 PM, Johan Brichau <[hidden email]> wrote:

> Hi Esteban,
>
> I don't think you need the extra #element method.
> How about the following:
>
>         WAJsonCanvas builder render: [ :json |
>                 json array: [
>                         WADocument  allSubclasses do:[:each |
>                                 json value: [  json object: [ json key: 'name' value: each name ] ]]]
>
> this produces:
>
>         '[{"name": "WAXmlDocument"}, {"name": "WAJsonDocument"}, {"name": "WAHtmlDocument"}, {"name": "WAUnescapedDocument"}, {"name": "WAPrettyPrintedDocument"}]'
>
> But this example makes me think... I would actually want to write it as follows:
>
>         WAJsonCanvas builder render: [ :json |
>                 json array: [
>                         WADocument  allSubclasses do:[:each |
>                                 json object: [ json key: 'name' value: each name ]]]]
>
> i.e. without the #value: message. I would expect the canvas to put a comma in between different objects. An 'object' is actually a 'value' in the json syntax.
> It might make sense.

That's a pretty simple fix

WAJsonObjectBrush >> #openBrush
    canvas writeIfNotFirst: ', '.
    self document openObject

seems to do the trick. I'm a bit reluctant to commit because I'm not
sure if it will break anything. Tests are green though.

Cheers
Philippe
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: WAJsonCanvas

Esteban A. Maringolo
In reply to this post by Johan Brichau-2
2014-02-22 17:15 GMT-03:00 Johan Brichau <[hidden email]>:
> Hi Esteban,

> But this example makes me think... I would actually want to write it as follows:
>
>         WAJsonCanvas builder render: [ :json |
>                 json array: [
>                         WADocument  allSubclasses do:[:each |
>                                 json object: [ json key: 'name' value: each name ]]]]

> i.e. without the #value: message. I would expect the canvas to put a comma in between different objects. An 'object' is actually a 'value' in the json syntax.
> It might make sense.

Yes, I would expect that usage too.

But even when it's not a common use case scenario, you could have a
mixed objects array.

Something like: ['string', 3.14, {key: 'value', foo: 'baz'}, [...], false]

In that case it wouldn't be just "extending" the WAJsonObjectBrush
openTag, but it should be something at other level, that let you
manage the elements any way you want. Hence the #element: method.

Regards,

Esteban A. Maringolo
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: WAJsonCanvas

Johan Brichau-2
Hi Esteban,

> But even when it's not a common use case scenario, you could have a
> mixed objects array.
>
> Something like: ['string', 3.14, {key: 'value', foo: 'baz'}, [...], false]
>
> In that case it wouldn't be just "extending" the WAJsonObjectBrush
> openTag, but it should be something at other level, that let you
> manage the elements any way you want. Hence the #element: method.

I believe this is exactly the way #value: works.
Is there a reason why the following does work for you in such a case?

WAJsonCanvas builder render: [ :json |
        json value:  (Array with: 'string' with: 3.14 with: (Dictionary new at: 'key' put: 'value';yourself))
        ]

The way I understand how the canvas is designed is that #value still supports the 'old-style' conversion of Smalltalk object to json, and that #object:, #array, etc. allow to build json directly without the intermediate stop of building arrays and dictionaries. But I must admit I have not played with the JSON Canvas in 3.1 yet.

Johan_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: WAJsonCanvas

Johan Brichau-2
In reply to this post by Philippe Marschall

On 22 Feb 2014, at 22:54, Philippe Marschall <[hidden email]> wrote:

> That's a pretty simple fix
>
> WAJsonObjectBrush >> #openBrush
>    canvas writeIfNotFirst: ', '.
>    self document openObject
>
> seems to do the trick. I'm a bit reluctant to commit because I'm not
> sure if it will break anything. Tests are green though.

Though it is an interface change, perhaps it's the best thing to change it now (for 3.1.1) before too many people have migrated to Seaside 3.1 ?
Mind that I am also changing the jQuery and jQueryUI packages to their latest versions, so 3.1.1 will have a couple of interface changes anyway. Unless we decide to postpone the jQuery upgrade (which is not a good idea imho) to 3.2 ?

Johan_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: WAJsonCanvas

Esteban A. Maringolo
In reply to this post by Johan Brichau-2
Hi Johan,

2014-02-24 15:47 GMT-03:00 Johan Brichau <[hidden email]>:

> Hi Esteban,
>
>> But even when it's not a common use case scenario, you could have a
>> mixed objects array.
>>
>> Something like: ['string', 3.14, {key: 'value', foo: 'baz'}, [...], false]
>>
>> In that case it wouldn't be just "extending" the WAJsonObjectBrush
>> openTag, but it should be something at other level, that let you
>> manage the elements any way you want. Hence the #element: method.
>
> I believe this is exactly the way #value: works.
> Is there a reason why the following does work for you in such a case?
>
> WAJsonCanvas builder render: [ :json |
>         json value:  (Array with: 'string' with: 3.14 with: (Dictionary new at: 'key' put: 'value';yourself))
>         ]
>
> The way I understand how the canvas is designed is that #value still supports the 'old-style' conversion of Smalltalk object to json, and that #object:, #array, etc. allow to build json directly without the intermediate stop of building arrays and dictionaries. But I must admit I have not played with the JSON Canvas in 3.1 yet.

It works that way if you already have the collection and it's
converted to its JSON representation, but if you're building a JSON
that doesn't exactly maps the "structure" of your objects, then you
can't. Or even if you're creating a JSON that doesn't look anything
like the receiver's object graph. (*)

Or... if I'm fetching objects from a forward only collection (stream,
database, etc.) and serializing them as JSON, I don't have (nor want
to have either) the whole objects collection in memory.

e.g. (unsafe/naive iteration)

WAJsonCanvas builder render: [ :json |
  json array: [
    [ aStream atEnd ] whileFalse: [
         json element: [json value: aStream next]
        ]
   ]
]


If instead of #element: I use #value: I get all the elements rendered
at JSON but with no element separator. It is... without any commas in
between.


Regards!




Esteban A. Maringolo


(*) That's why I used the old #jsonOn: instead of the stream based
NeoJSON, because it was simpler to me to build the intermediate
dictionaries and convert everything to a JSON string at the end, with
memory penalty of having a huge nested dictionaries object graph.
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: WAJsonCanvas

Philippe Marschall
In reply to this post by Johan Brichau-2
On Mon, Feb 24, 2014 at 7:50 PM, Johan Brichau <[hidden email]> wrote:

>
> On 22 Feb 2014, at 22:54, Philippe Marschall <[hidden email]> wrote:
>
>> That's a pretty simple fix
>>
>> WAJsonObjectBrush >> #openBrush
>>    canvas writeIfNotFirst: ', '.
>>    self document openObject
>>
>> seems to do the trick. I'm a bit reluctant to commit because I'm not
>> sure if it will break anything. Tests are green though.
>
> Though it is an interface change, perhaps it's the best thing to change it now (for 3.1.1) before too many people have migrated to Seaside 3.1 ?

The thing is I'm not sure it's an actual interface change. Sure, new
code written against the new version will not work against the old
version but I'm not sure that code written against the old version
will break.

> Mind that I am also changing the jQuery and jQueryUI packages to their latest versions, so 3.1.1 will have a couple of interface changes anyway. Unless we decide to postpone the jQuery upgrade (which is not a good idea imho) to 3.2 ?

Doing this now is correct IMHO.

Cheers
Philippe
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside