In the meantime I have worked a little bit on this and in "sandbox/rony/json" you will find the version that I intend to use which has the following additional changes:

 * toJSONFile will by default (like toJSON) create a minimized JSON rendering 
unless the optional
   legible argument is supplied with a value of .true,
 * the methods toJSON and fromJSON can now be used as class methods such that 
one does not have to
   create a JSON instance anymore (this ability remains in place such that 
programs that use the
   instance keep on running),
 * the conversions are now documented:

   The methods toJSON and toJSONFile will render Rexx objects as follows:
   • An instance of type String: replaces all double-quotes with the escape sequence 
\" and
   encloses the string value in double quotes, unless the string is a valid 
Rexx number in which
   case the string is used as is and no enquoting takes place
   • An instance of type MapCollection: creates a comma separated list of 
name/value pairs
   enclosed in curly brackets.
   • An instance of type OrderedCollection: creates a comma separated list of 
ordered values
   enclosed in square brackets.
   • An object that is .nil as the unquoted string null.
   • An object that has a method named makeJson (supporting the ooRexx request 
protocol for
   conversion to JSON): uses the string that makeJson is expected to return.
   The JSONBoolean false value will be rendered as the unquoted string false, 
the true value will
   be rendered as the unquoted string true.
   • An object that has a method named makeArray (supporting the ooRexx request 
protocol for
   conversion to an ooRexx Array): uses the returned array that makeArray is 
expected to return
   and renders it as an OrderedCollection (see above).
   • An object that has a method named makeString (supporting the ooRexx 
request protocol for
   conversion to an ooRexx String): uses the string that makeString is expected 
to return and
   renders it as a String (see above).
   • An object for which a conversion to JSON is unknown: sends the string 
message and
   renders the resulting string as a String (see above).

Also the rexxextensions.pdf is in the sandbox such that you can inspect the generated JSON documentation with the additions.

A direct link to the json sandbox on SourceForge is: <https://sourceforge.net/p/oorexx/code-0/HEAD/tree/sandbox/rony/json/>.

Any feedback welcome.

---rony


On 02.02.2023 17:10, Rony G. Flatscher wrote:

Thank you Jon, for your thumbs up! Will wait a day or two before committing to 
trunk.

---rony


On 02.02.2023 13:42, Sahananda Sahananda wrote:
Thank you Rony.  👏

I have had to use terrible kludges to get over the otherwise remarkably usable JSON class's habit of turning JSON booleans into ooRexx booleans.  This will be a great boon.

+1 to adding this to the language proper.

Jon

On Thu, 2 Feb 2023 at 12:37, Rony G. Flatscher <rony.flatsc...@wu.ac.at> wrote:

    "json.cls" as distributed with ooRexx 5.0.0 has one (actually two) 
limitation which can be
    regarded to be a bug:

      * It cannot handle JSON booleans properly: when reading a JSON file with 
boolean values and
        creating a JSON file from ooRexx the boolean values will not show up, 
rather their ooRexx
        numeric representations of "0" and "1".

    In the past I came up with a solution for this problem which was not 
"liked" and was 30%
    slower than json.cls (sounds dramatic, but in today's world with such power 
horses in the
    hands of end-users may be negligeable, but still, one being made aware of 
this made it less
    attractive).

    As the above limitation is really a problem if one wants to use ooRexx 
json.cls and exchange
    proper JSON with other systems, e.g. via curl, I came up with a version 
(starting out with
    the current json.cls) that does the following in addition:

      * It adds support for JSON true and false: just send .json~true or 
.json~false. The
        resulting JsonBoolean objects behave like ooRexx .true and .false (both 
strings with the
        numeric values "0" and "1") and can be used interchangeably

          o when reading a JSON file, JSON booleans will be represented with 
the appropriate
            .json~true or .json~false values

          o when writing a JSON file, any JSON boolean value will be properly 
encoded with
            "false" and "true"

      * It adds generic support for MapCollection and OrderedCollection instead 
of restricting
        support to Directory and Array,

      * It uses StringTable instead of Directory for reading in JSON data,

      * Although JSON is a string encoding, which could be read by humans, 
there are two
        observable properties that do not make it human-friendly:

          o by default the encoding is "minimized" such that no ignorable 
whitespace (usually
            used for making JSON better legible e.g. cf. Wikipedia's JSON [1] 
sample) is contained,

          o there is no sorted order of name/value pairs (per specification no 
order is implied,
            yet for humans having a sorted order in the JSON encoded data makes 
it possible to
            quickly check whether certain name/values pairs exist or not 
without affecting any
            JSON importer)

        the replacement version will create by default minimized JSON 
encodings, however it will
        sort name/value pairs by name to ease reading by humans

      * as this is Rexx/ooRexx it is made possible to create a "legible", a 
"human-oriented" JSON
        encoding in two ways: when creating a JSON instance or when sending the 
toJson message
        one can supply .true which causes the produced JSON encoding to be 
formatted with
        ignorable whitespace such that it will be easy to see the structure and 
spot name/value
        pairs therein; yet, the produced JSON is still JSON and can be 
processed without problems,

      * two new convenience class methods for reading from and writing to files 
are defined:
        fromJsonFile(fileName) and toJsonFile(fileName, ooRexxObject [, 
legible=.true])

    Here the JSON sample given at [1]:

        {
        "firstName":"John",
        "lastName":"Smith",
        "isAlive":true,
        "age":27,
        "address":{
        "streetAddress":"21 2nd Street",
        "city":"New York",
        "state":"NY",
        "postalCode":"10021-3100"
        },
        "phoneNumbers":[
        {
        "type":"home",
        "number":"212 555-1234"
        },
        {
        "type":"office",
        "number":"646 555-4567"
        }
        ],
        "children":[
        "Catherine",
        "Thomas",
        "Trevor"
        ],
        "spouse":null
        }

    Here the minimized rendering with the replacement version of json.cls:

        {"address":{"city":"New York","postalCode":"10021-3100","state":"NY","streetAddress":"21 2nd 
Street"},"age":27,"children":["Catherine","Thomas","Trevor"],"firstName":"John","isAlive":true,"lastName":"Smith","phoneNumbers":[{"number":"212 555-1234","type":"home"},{"number":"646 
555-4567","type":"office"}],"spouse":null}

    Here the legible rendering with the replacement version of json.cls:

        {
            "address": {
               "city": "New York",
               "postalCode": "10021-3100",
               "state": "NY",
               "streetAddress": "21 2nd Street"
            },
            "age": 27,
            "children": [
               "Catherine",
               "Thomas",
               "Trevor"
            ],
            "firstName": "John",
            "isAlive": true,
            "lastName": "Smith",
            "phoneNumbers": [
               {
                  "number": "212 555-1234",
                  "type": "home"
               },
               {
                  "number": "646 555-4567",
                  "type": "office"
               }
            ],
            "spouse": null
        }

    ---

    Here an ooRexx program that creates a structure which will get encoded as 
minimized and
    legible JSON:

        -- create a Rexx structure
        d=.directory~new
        d["firstName"] = "Mary"
        d["lastName" ]  = "Doe"
        d["children" ]  = .list~of("Maribel", "John", "Annabel")
        d["married"  ]  = .json~false
        d["born"     ]  = "2001-02-02"
        d["yearBorn" ]  = 2001
        d["bestMan"  ]  = .nil

        j = .json~new
        say j~toJson(d)         -- write minimized JSON
        say "---"
        say j~toJson(d,.true)   -- write legible JSON

        ::requires "json.cls"   -- get access to the JSON class

    Here the output of the above program:

        
{"bestMan":null,"born":"2001-02-02","children":["Maribel","John","Annabel"],"firstName":"Mary","lastName":"Doe","married":false,"yearBorn":2001}
        ---
        {
            "bestMan": null,
            "born": "2001-02-02",
            "children": [
               "Maribel",
               "John",
               "Annabel"
            ],
            "firstName": "Mary",
            "lastName": "Doe",
            "married": false,
            "yearBorn": 2001
        }

    ---

    The replacement json.cls and the adjusted official json.tesgroup can be 
found in my sandbox
    at <https://sourceforge.net/p/oorexx/code-0/HEAD/tree/sandbox/rony/json/>
    <https://sourceforge.net/p/oorexx/code-0/HEAD/tree/sandbox/rony/json/>.

    Performance when reading and writing is comparable to 5.0's json.cls.

    ---rony

    [1] Wikipedia JSON: <https://en.wikipedia.org/wiki/JSON> 
<https://en.wikipedia.org/wiki/JSON>

_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to