Seaside Json serialization for Dictionary, Collection does not recursive jsonOn: aStream ?

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

Seaside Json serialization for Dictionary, Collection does not recursive jsonOn: aStream ?

Bart Gauquie
Dear all,

I'm creating a jquery plugin in seaside for jqgrid and trying out the json way of loading data. I've noticed following behaviour while trying to convert a Dictionary, Collection to a Json string.

This is the expected result:
{"page":"1",
  "total":2,
  "records":"13",
   "rows":
      [{"id":"1","cell":["1","2007-10-01","Client 1","100.00","20.00","120.00","note 1"]},
    {"id":"3","cell":["3","2007-10-02","Client 2","300.00","60.00","360.00","note for invoice 3"]},
    {"id":"2","cell":["2","2007-10-03","Client 1","200.00","40.00","240.00","note 2"]},
    {"id":"4","cell":["4","2007-10-04","Client 3","150.00","0.00","150.00","no tax"]}]}

I've created some classes to generate this structure automatically.
JQRowContent with an id and a rows array. 

JQRowContent>>jsonOn: aStream
(Dictionary newFrom: {'id'->id. 'cell'->columnValues}) jsonOn: aStream

And the JQGridSearchResponse with a page, totalNumberOfPages, totalNumberOfRecords and rowContents:

JQGridSearchResponse>>jsonOn: aStream
(Dictionary newFrom:
{'page'->page.
'total'->totalNumberOfPages.
'records'->totalNumberOfRecords.
'rows'->rowContents})
jsonOn: aStream

Writing out the response is then just:
searchResponse jsonOn: response stream

However, out of the box, using Seaside 3.0 with Javascript-Core-lr.74 it does not work as expected. 

I get the following result:
'{"page":1,"total":1,"rows":[a JQGridRowContent,a JQGridRowContent,a JQGridRowContent,a JQGridRowContent,a JQGridRowContent],"records":100000}'

Meaning that the collection of rowContents of the dictionary did not get json encoded recursively. Is this the normal behaviour? If I look at
JSStream>>encodeKey: aKey value: aValue on: aStream
self encodeKey: aKey on: aStream.
aStream nextPut: $:; javascript:aValue

You see that the value (rowcontents array) gets encoded as plain javascript and not as json.
Overriding this method in JSJsonStream (which was used) :
JSJsonStream>>encodeKey: aKey value: aValue on: aStream
self encodeKey: aKey on: aStream.
aStream nextPut: $:.
aValue jsonOn: aStream.

and also overriding:

JSJsonStream>>encodeCollection: aCollection on: aStream
aStream nextPut: $[.
aCollection
do: [:each|each jsonOn: aStream]
separatedBy: [aStream nextPut: $,].
aStream nextPut: $]

gives the correct result.

The above code should get further refactored (2 much duplication) by extracting in JSStream a method to encode a value:

JSStream>>encodeValue: aValue on: aStream
aStream javascript: aValue

using this method in #encodeCollection on:, #encodeKey: value: on:, and others from JSStream.

and off course overriding this in JSJsonStream.
JSJsonStream>>encodeValue: aValue on: aStream
aValue jsonOn: aStream

(and maybe adding
Stream>>json: anObject
anObject jsonOn: self)

Is the behaviour I'm experiencing a known issue? Or is there a reason it is designed this way? I've searched the mailing/bug list but could not find anything.

Thanks for any help.

Kind Regards,

Bart










--
imagination is more important than knowledge - Albert Einstein
Logic will get you from A to B. Imagination will take you everywhere - Albert Einstein
Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning. - Albert Einstein
The true sign of intelligence is not knowledge but imagination. - Albert Einstein
However beautiful the strategy, you should occasionally look at the results. - Sir Winston Churchill
It's not enough that we do our best; sometimes we have to do what's required. - Sir Winston Churchill

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

Re: Seaside Json serialization for Dictionary, Collection does not recursive jsonOn: aStream ?

Julian Fitzell-2
Hi Bart,

Your analysis looks about right to me. It's not a known bug - there just aren't really any users of the JSON stuff yet and I suspect none of them are encoding custom classes.

Care to submit a fix? Either way, you could create an issue at http://code.google.com/p/seaside/issues/list .

Cheers,

Julian

On Sun, Jan 31, 2010 at 9:14 AM, Bart Gauquie <[hidden email]> wrote:
Dear all,

I'm creating a jquery plugin in seaside for jqgrid and trying out the json way of loading data. I've noticed following behaviour while trying to convert a Dictionary, Collection to a Json string.

This is the expected result:
{"page":"1",
  "total":2,
  "records":"13",
   "rows":
      [{"id":"1","cell":["1","2007-10-01","Client 1","100.00","20.00","120.00","note 1"]},
    {"id":"3","cell":["3","2007-10-02","Client 2","300.00","60.00","360.00","note for invoice 3"]},
    {"id":"2","cell":["2","2007-10-03","Client 1","200.00","40.00","240.00","note 2"]},
    {"id":"4","cell":["4","2007-10-04","Client 3","150.00","0.00","150.00","no tax"]}]}

I've created some classes to generate this structure automatically.
JQRowContent with an id and a rows array. 

JQRowContent>>jsonOn: aStream
(Dictionary newFrom: {'id'->id. 'cell'->columnValues}) jsonOn: aStream

And the JQGridSearchResponse with a page, totalNumberOfPages, totalNumberOfRecords and rowContents:

JQGridSearchResponse>>jsonOn: aStream
(Dictionary newFrom:
{'page'->page.
'total'->totalNumberOfPages.
'records'->totalNumberOfRecords.
'rows'->rowContents})
jsonOn: aStream

Writing out the response is then just:
searchResponse jsonOn: response stream

However, out of the box, using Seaside 3.0 with Javascript-Core-lr.74 it does not work as expected. 

I get the following result:
'{"page":1,"total":1,"rows":[a JQGridRowContent,a JQGridRowContent,a JQGridRowContent,a JQGridRowContent,a JQGridRowContent],"records":100000}'

Meaning that the collection of rowContents of the dictionary did not get json encoded recursively. Is this the normal behaviour? If I look at
JSStream>>encodeKey: aKey value: aValue on: aStream
self encodeKey: aKey on: aStream.
aStream nextPut: $:; javascript:aValue

You see that the value (rowcontents array) gets encoded as plain javascript and not as json.
Overriding this method in JSJsonStream (which was used) :
JSJsonStream>>encodeKey: aKey value: aValue on: aStream
self encodeKey: aKey on: aStream.
aStream nextPut: $:.
aValue jsonOn: aStream.

and also overriding:

JSJsonStream>>encodeCollection: aCollection on: aStream
aStream nextPut: $[.
aCollection
do: [:each|each jsonOn: aStream]
separatedBy: [aStream nextPut: $,].
aStream nextPut: $]

gives the correct result.

The above code should get further refactored (2 much duplication) by extracting in JSStream a method to encode a value:

JSStream>>encodeValue: aValue on: aStream
aStream javascript: aValue

using this method in #encodeCollection on:, #encodeKey: value: on:, and others from JSStream.

and off course overriding this in JSJsonStream.
JSJsonStream>>encodeValue: aValue on: aStream
aValue jsonOn: aStream

(and maybe adding
Stream>>json: anObject
anObject jsonOn: self)

Is the behaviour I'm experiencing a known issue? Or is there a reason it is designed this way? I've searched the mailing/bug list but could not find anything.

Thanks for any help.

Kind Regards,

Bart










--
imagination is more important than knowledge - Albert Einstein
Logic will get you from A to B. Imagination will take you everywhere - Albert Einstein
Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning. - Albert Einstein
The true sign of intelligence is not knowledge but imagination. - Albert Einstein
However beautiful the strategy, you should occasionally look at the results. - Sir Winston Churchill
It's not enough that we do our best; sometimes we have to do what's required. - Sir Winston Churchill

_______________________________________________
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: Seaside Json serialization for Dictionary, Collection does not recursive jsonOn: aStream ?

Nick
In reply to this post by Bart Gauquie

Is the behaviour I'm experiencing a known issue? Or is there a reason it is designed this way? I've searched the mailing/bug list but could not find anything.


Hi Bart,
I've just come across the same issue with Json encoded arrays - but when I searched I came across your helpful mail. Are you planning to submit your fix?

On a related Json issue, I found that code I was writing for Json encoding my classes followed a similar pattern - I'd encode all the instance variables in a Dictionary. I extracted this code and made it generic as:

Object>>jsonOn: aStream
| attributes |
attributes := Dictionary new.
self class instVarNames do:
[ :ivarName | 
attributes 
at: ivarName
put: (self instVarNamed: ivarName) ].
JSStream encodeDictionary: attributes on: aStream.

I wonder if this would be sufficiently generally applicable to appear in the default distribution? Classes can always override the default for custom Json encoding.

Thoughts?

Nick

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

Re: Seaside Json serialization for Dictionary, Collection does not recursive jsonOn: aStream ?

Bart Gauquie
Hi,

I will create a bug for it and I'm more than happy to create fix it. 
Can anyone please add me as a seaside developer on squeaksource. (user=bkbag). Thanks.

On a related Json issue, I found that code I was writing for Json encoding my classes followed a similar pattern - I'd encode all the instance variables in a Dictionary. I extracted this code and made it generic as:

Object>>jsonOn: aStream
| attributes |
attributes := Dictionary new.
self class instVarNames do:
[ :ivarName | 
attributes 
at: ivarName
put: (self instVarNamed: ivarName) ].
JSStream encodeDictionary: attributes on: aStream.

I wonder if this would be sufficiently generally applicable to appear in the default distribution? Classes can always override the default for custom Json encoding.

Thoughts?

Nick

I've also noticed this. There is no implementation of jsonOn: aStream on Object class right now. 
Your implementation seems like a sensible default thing to do.
Its actually highly related to http://code.google.com/p/seaside/issues/detail?id=449 (Generating JSON is difficult) bug.

Kind Regards,

Bart


--
imagination is more important than knowledge - Albert Einstein
Logic will get you from A to B. Imagination will take you everywhere - Albert Einstein
Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning. - Albert Einstein
The true sign of intelligence is not knowledge but imagination. - Albert Einstein
However beautiful the strategy, you should occasionally look at the results. - Sir Winston Churchill
It's not enough that we do our best; sometimes we have to do what's required. - Sir Winston Churchill

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

Re: Seaside Json serialization for Dictionary, Collection does not recursive jsonOn: aStream ?

Bart Gauquie
I've created http://code.google.com/p/seaside/issues/detail?id=543.

Regards,

Bart


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

Re: Seaside Json serialization for Dictionary, Collection does not recursive jsonOn: aStream ?

Bart Gauquie
Dear all,

I've created a test and a fix on my local image. 

I've also added:

Stream>>json: anObject
anObject jsonOn: self

(analogous 2 Stream>>javascript: anObject)

I've also noticed that there is a Javascript-Pharo-Core which
contains: 
GRCodecStream>>javascript: anObject
I've also added the json: method on that class.

Where can I put my packages so that a more experienced seaside developer can take a look at it and give feedback? 

Thanks

Kind Regards,

Bart

--
imagination is more important than knowledge - Albert Einstein
Logic will get you from A to B. Imagination will take you everywhere - Albert Einstein
Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning. - Albert Einstein
The true sign of intelligence is not knowledge but imagination. - Albert Einstein
However beautiful the strategy, you should occasionally look at the results. - Sir Winston Churchill
It's not enough that we do our best; sometimes we have to do what's required. - Sir Winston Churchill

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