Thursday, September 19, 2019

Parse JSON in pure X++

I decided to write a JSON parser in X++, because I couldn't find a useful implementation elsewhere. I wanted to avoid using external dll-based libraries.

It can handle strings, numbers (int and real), null-values and booleans. All kinds of linebreaks will be ignored.

It can be used like this:
str json = '{"foo": [1, 2, {"bar": 2}, {"bar": 3}]}';

AhkJSONObject ele = AhkJSONParser::parse(json);
AhkJSONArray arr = ele.get("foo");
AhkJSONObject obj = arr.get(3);
;

info('Demo 1: bar=' + obj.get("bar").strVal());
info('Demo 2: bar=' + AhkJSONParser::parse(json).getObjVal('foo').getArrayItem(3).getObjVal('bar').strVal());
info('Demo 3: bar=' + AhkJSONParser::parse(json).getObjVal('foo').getArrayItemWhere('bar', '3').getObjVal('bar').strVal());


Which will output:
Demo 1: bar=2
Demo 2: bar=2
Demo 3: bar=3

Please note the selection in demo 3, which makes it easy to select the correct array item. The project can be downloaded from the following url and is exported from AX 2009:
https://oc.ahkpro.dk/index.php/s/Q52BQ56zyrp2co8

The implementation is largely based on this python project:
https://github.com/eatonphil/pj/tree/master/pj

2020-01-20 update: I have updated the project with a few bugfixes, which should solve the two issues reported in comments.
2020-03-30 update: I have updated the project with a fix for parsing arrays as the outer type.

12 comments:

  1. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Hi rabol. I'm not sure why your original comment about Som json which couldn't be parsed was removed, but it should be solved now with the new project I've uploaded.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. It would be cool if it also could generate JSON

    ReplyDelete
  4. Hi,
    The above code is failing while parsing JSON:
    {"shipping_address": {
    "first_name": "Kristen",
    "offer": "use promo code \"sing20\""
    }
    }
    Please help me how to proceed.

    ReplyDelete
    Replies
    1. I've uploaded a new project. Please try again 🙂

      Delete
  5. This will not parse
    str json = '[{"foo": [1, 2, {"bar": 2}, {"bar": 3}]}]';

    ReplyDelete
    Replies
    1. Try the new version (1.2). Now the following works:
      str json = '[{"foo": [1, 2, {"bar": 2}, {"bar": 3}]}]';
      AhkJSONArray ele = AhkJSONParser::parse(json);
      ;
      info(int2str(ele.getArrayItem(1).getObjVal('foo').getArrayItem(1).intVal()));

      Delete
  6. How to iterate over the parsed JSON

    imagine this
    str json = "{
    "messageid": 1,
    "messageTxt": "This is a test 1"
    },
    {
    "messageid": 2,
    "messageTxt": "This is a test 2"
    }";

    the AhkJSONParser::parse(json); is a object, but it is not possible to see how many elements

    ReplyDelete
    Replies
    1. Try enclosing the objects in brackets to make it an array :) Otherwise it isn't valid JSON.

      Delete
  7. Thank you, I really like your solution.
    I ran into a problem with large numbers. I had to add a new class to your parser (AhkJSONInt64).

    And I extended your AhkJSONLex.lex_number()
    ...
    else if(str2int64(json_number) > global::intMax())
    tokens.value(tokens.lastIndex()+1, new AhkJSONInt64(str2int64(json_number)));
    ...

    ReplyDelete
  8. How I can iterate
    [
    {
    "name": "Harry Potter",
    "city": "London"
    },
    {
    "name": "Don Quixote",
    "city": "Madrid"
    }
    ]

    ReplyDelete