eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'JSONReader':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: JSONReader


Inheritance:

   Object
   |
   +--Stream
      |
      +--PeekableStream
         |
         +--JSONReader

Package:
stx:goodies/communication
Category:
Net-Communication-JSON
Version:
rev: 1.34 date: 2019/08/17 22:21:14
user: cg
file: JSONReader.st directory: goodies/communication
module: stx stc-classLibrary: communication

Description:


I read data structures (currently build of OrderedCollection and Dictionary)
from and to JSON (Java Script Object Notation). 
Writing is done with the #toJSON: class-method (note: it will behave badly with circular data structures).
Reading via the #fromJSON: class-method.

Notice: 
    By default (and standard), 
    Date, Time and Timestamps are written as iso8601 strings,
    and read initially as strings (thus, they must be converted explicitely back if required).

    The non-standard (but supported by some browsers) format is 'new Date(...)' which is generated
    optionally, if the useISODateFormat flag is turned off in the JSONPrinter.
    However, we cannot read back this format.
    As per ECMA,
        JSON.stringify({'now': new Date()}) 
    should generate
        {''now'':''2013-10-21T13:28:06.419Z''}
    which is exactly what JSONPrinter now generates by default
        JSONPrinter encode:(Structure with: #now -> (Timestamp now)).

Another Note:
    Can now also encode arbitrary Smalltalk objects; however, the reader will always decode them 
    as dictionaries:
        JSONPrinter encode:(Point x:10 y:20).
        JSONReader decode:(JSONPrinter encode:(Point x:10 y:20)).

Final Notice:
    take a look at the other (alternative) JSON framework (Json),
    which can also be used to handle JSON data, and offers a more flexible
    object mapping mechanism to decode into real objects.

Author:
    Public Domain Code from Robin Redeker published in lists.gnu.org
    adapted to ST/X by Claus Gittinger


Class protocol:

API - decoding
o  decode: stringOrStream
decode the JSON string (as received from JavaScript) to an object

o  fromJSON: stringOrStream
decode the JSON string (as received from JavaScript) to an object.
Same as decode:
Added to make the decoder protocol-conform to other encoders.

o  readFrom: stringOrStream
decode the JSON string (as received from JavaScript) to an object.
Same as decode:
Added to make the decoder protocol-conform to other encoders.

API - encoding
o  encode: anObject
return a JSON string which represents the object (can be sent to JavaScript).
Same as toJSON:
Added to make this more protocol-conform to other encoders.

o  toJSON: anObject
return a JSON string which represents the object (can be sent to JavaScript).
Same as encode:
Added to make this more protocol-conform to other encoders.

o  toJSON: anObject on: aStream
append a JSON string which represents the object (can be sent to JavaScript)
to aStream.
Same as encode:
Added to make this more protocol-conform to other encoders.

usage example(s):

     self toJSON:#('hello' 123 true (1 'two' 3.0)) on:Transcript.

instance creation
o  new
return an initialized instance

o  on: aStream


Instance protocol:

initialization
o  initialize
JSONPrinter encode:((10@20) corner:(100@200))

o  makeSlotDecoderFor: typeInfoFormat

o  typeInfoFormat: formatSymbolOrNil
specify the format of the type info to be store with the slots.
For now, the formats supported are:
nil (default): no type info (standard JSON)
#stx : encode as { '@type': , <classNameString> , 'value': <encoding> }
more formats may be implemented in the future.

private
o  atEnd

o  next
I'm returning the next non-whitespace character

o  nextJSONArray
I decode JSON arrays from self and will return an Array for them.

o  nextJSONDict
I decode JSON objects from self and will return a Dictionary containing all the key/value pairs.

o  nextJSONNumber
I'm extracting a number in JSON format from self and return Integer or Float depending on the input.

o  nextJSONString
I'm extracting a JSON string from self and return it as String.

o  peek
I'm peeking for the next non-whitespace character and will drop all whitespace in front of it

o  stream: aStream

reading
o  decode: stringOrStream

o  nextJSONObject
I decode a json self to a value, which will be one of:
nil, true, false, OrderedCollection, Dictionary, String or Number
(I will return Integer or Float depending on the input).


Examples:


    |o1 s o2|
    o1 := #('hello' 123 nil true false (1 'two' 3.0) -4 -1.5).
    s := JSONPrinter toJSON:o1.   
    o2 := JSONReader fromJSON:s.   
    self assert:(o1 = o2).  
    |o1 s o2|
    o1 := InlineObject slotNames:#('foo' 'bar' 'baz') values:#(1 2 3).
    s := JSONPrinter toJSON:o1.  
    o2 := JSONReader fromJSON:s.    
    |o1 s o2|
    o1 := OrderedDictionary withKeys:#('foo' 'bar' 'baz') andValues:#(1 2 3).
    s := JSONPrinter toJSON:o1.  
    o2 := JSONReader fromJSON:s.   
    self assert:(o1 = o2).
    |o1 s o2|
    o1 := Dictionary withKeysAndValues:#('one' 1 'two' 2 'three' 3.0 'four' 'vier').
    s := JSONPrinter toJSON:o1.
    o2 := JSONReader fromJSON:s.   
    self assert:(o1 sameContentsAs: o2).
    |o1 s o2|
    o1 := Dictionary withKeysAndValues:#('one two three' 123).
    s := JSONPrinter toJSON:o1.
    o2 := JSONReader fromJSON:s.   
    self assert:(o1 sameContentsAs: o2).
    |o1 s o2|
    o1 := { Date today . Time now . Timestamp now }.
    s := JSONPrinter encode:o1.
    o2 := JSONReader decode:s.
    -- notice: data & times are decoded as strings
    |o1 s o2|
    o1 := { Point x:10 y:20 }.
    s := JSONPrinter new useISODateFormat:false; encode:o1.
    o2 := JSONReader decode:s.
    self assert:(o1 sameContentsAs: o2).
    |o1 s o2|
    o1 := { Date today . Time now . Timestamp now }.
    s := JSONPrinter new useISODateFormat:false; encode:o1.
    o2 := JSONReader decode:s -- fails as non-JSON  


ST/X 7.2.0.0; WebServer 1.670 at bd0aa1f87cdd.unknown:8081; Sat, 20 Apr 2024 12:10:21 GMT