[ardoJSON] Documentation

Forge Component
Published on 2018-10-24 by Ricardo Silva
29 votes
Published on 2018-10-24 by Ricardo Silva

What Is It

ardoJSON is an extension which aims to provide a simple interface to processing JSON data. The goal is that no extension coding is required, you only have to define the relevant structures in OutSystems and the extension will do the rest for you.

It is capable of serializing any data from the OutSystems Platform into JSON, and it is capable of de-serializing JSON into a compliant OutSystems structure.


ardoJSON provides three actions, one for writing an OutSystems Platform value into JSON, one for reading JSON data and constructing OutSystems Platform structures, and a last one which allows you to select relevant JSON from complex JSON data.

  • OutSystems2JSON
  1. Value (Object): The value to be serialized. This can be anything in the OutSystems types, a string, an integer, a decimal, a record, a record list. The value must be passed using the ToObject() builtin function.
  2. DateFormat [Optional] (Integer): This parameter controls how dates are serialized. By default they are serialized as javascript timestamps (miliseconds since epoch), but it is also possible to use ISO 8601, or /Date(timestamp)/ formats. Use 0 for timestamps, 1 for ISO 8601 full string, 2 for /Date/, and 3 for a heuristic version of ISO 8601, which tries to detect if the value is a Date, a DateTime or a Time in Service Studio. The default in version 1.0 is 0, in version 1.1 is 3.
  1. JSON (Text): A JSON representation of the povided object.

This action will serialize basic types to JSON values, Record Lists to arrays, Records to objects.

Record List flattening: A Record List whose record only contains one attribute will be flattened, so instead of serializing to something like [ {"value": 1}, {"value": 2} ], it will serialize to [ 1 , 2 ].

Record joins are NOT supported. In the best case scenario, only one of the records will be serialized, in the worst case scenario, an error occurs.

  • JSON2RecordList
  1. JSON (Text): The JSON data to de-serialize
  2. RecordList (Object): A Record List which will hold the de-serialized data. Should go without saying: the Record for the Record List's structure must match the data being deserialized.  This parameter must always be passed using the builtin ToObject function.

Due to OutSystems Platform limitations related to type safety and protection against data interference, this was the simplest way I could find to provide an interface. This function will take the JSON data from the text passed to it and deserialized it so it can be added to the Record List.

If the JSON data is a basic type and the Record contains an attribute named Value which matches the type, a record will be added to it.

If the JSON data is an array, all elements will be converted to OutSystems data structure and added to the record list.

If the JSON data is an object, a record will be created from it and added to the list.

Case Sensitivity: OutSystems record's attribute names are matched case insensitively against JSON object properties. This means that a json object { "name": "John  Doe" } will match with a record with a Text attribute named "Name", "NAME", etc.

Structural Matching: No checks will be made to ensure completeness of the JSON object, meaning that some attributes may be missing. In this case the default values for the attributes will be used.

Also, de-serialization will not fail if a matching attribute is not found on the Record. This is done to prevent changes in the interfaces one integrates with to start generating errors.

Flattened Lists: Not all lists in JSON data will be of objects (like the OutSystems lists are all of Records), most are likely to be lists of strings or numbers. These kind of lists are supported with the following convention:

When a list which is not of object is encountered, the attribute named (exactly) 'Value' will be used to set.

NEW: as of version 1.6, lists of non-objects (strings, numbers) are able to be deserializable by single attribute records. You don't have to name your attribute Value anymore. If deserializing a "flat" list to a record with more than one attribute, the attribute named Value will be the one which is chosen.

Heterogenous Lists:


Lists of whose elements are not all of the same type are an ABOMINATION and NOT SUPPORTED. Ask the JSON provider to use a SANE schema.

Null JSON Values:

Null Values are supported and will basically be handled as if they weren't there. The fields / array elements they define will not be assigned and thus retain their default values.

"Weird" Property Names:

In some JSON's you'll find some property names which are illegal in Service Studio, and in this case you'd have to pre-process the JSON to give them valid names, or accept their loss. No longer !

From version 1.1 of ardoJSON onwards these properties are automatically pre-processed in a deterministic manner, so you can create your attributes to match the resulting attribute.

Basically, anything which isn't an alphanumeric character is  translated to _ and leading invalid characters are removed. For example a JSON "_index" property will try to assign the value to an "index" attribute in OutSystems.

"9_index with^weird  characters" would be assigned to "index_with_weird_characters".

  • JSONSelect
  1. JSONIn (Text): JSON data to process
  2. Path (Text): A string describing which data to obtain from the original JSON Data. This string uses the dot notation to access object fields and bracket notation for indexing arrays.
  1. JSONOut (Text): JSON data which was selected from the path

Try it out in the demo, should be pretty straightforward to use.

How it works


Since all the matching is dynamic, this implementation is likely to never be as fast as a native custom implementation can be. I did make some effort to ensure that introspection is kept to a minimum.

The purpose of this extension is to speed-up your high-level feature development and integration. If performance becomes an issue, it may be a good idea to implement specific JSON serialization / de-serialization for the structures used by your application.

Date Handling

Dates are a pain in the neck. There is no standard for exchanging them, so I picked the ones which seem to be better adopted.

When de-serializing ardoJSON accepts any supported format.

There are three supported date formatting options:

Miliseconds since epoch. This is a relatively standard format which you can easily use to build a date in practically all programming languages. This is the default in version 1.0.

A more human readable format is ISO 8601, which outputs dates, datetimes and times as "2000-02-01T00:00:04".

Then I also support the /Date(miliseconds)/ format which is mentioned too extensively for my liking.

There is a third date format based on ISO 8601 which serializes dates trying to guess if it's a Date, DateTime or Time in Service Studio. It will output "1983-04-02" for a Date, ISO 8601 for DateTime, and "00:05:02" for a Time. This is now the default (as of 1.1)

Very useful and thanks for actually taking the time to write out this fine piece documentation. 

I'm sure it will be very useful to lots of people. 

Awesome Ricardo,

Great extension (very usefull let me say) and great documentation.

Gonçalo M.
I would like to ask everyone to create a new discussion if they are having problems with the ardoJSON extension, instead of adding to this Documentation discussion.
Documentation updated for the latest version of the component.
Hi Ricardo,

Would you please update the URL for ardoJSON demo eSpace, I tried to use the dropbox link but OutSystem Studio said it's not a valid OML file or the file is damaged.

I just tried downloading the demo eSpace from the link and it was working fine.

Maybe your file got corrupted somewhere along the way? Is anybody else experiencing this?

Also, I'd like to reiterate the request to open a new discussion for any problems you're having instead of adding to this one (unless you have questions about the usage of ardoJSON, those should go here).
can you give some (complex) examples how JSONSelect works?

Did you check the demo?

You can try it out with:


Any questions, let me know.
Ricardo Silva, what´s the date format to deserialize. I getting: "String was not recognized as a valid DateTime." and I tried "1900-01-01T00:00:00", "1900-01-01T12:00:00", "12:00:00", "1900-01-01". These are examples.
Hello Rogério,

All those should work with the more recent version of ardoJSON. I have tried them all at the demo without issues.

Can you provide us with the JSON you are trying to process and the eSpace where you define the structure ?
Hi Ricardo,
Is JSONSelect capable of filtering the JSON array with anything more complex than an index number?
I was thinking something like an XPath expression. i.e. director[lastName="Spielberg"]


Ricardo Silva wrote:
Did you check the demo?

You can try it out with:


Any questions, let me know.
Hello Adam,

JSONSelect uses functionality from the underlying library in .NET which does not support those kind of queries. The only supported type of queries are the kind of ones I have listed.

There is also no support for "JSONPath" (those kind of queries you mention) in jackson, or any kind of standard for it, so it would be hard to know exactly what to implement.

At the time I have no plans for enhancing the language supported by JSONSelect.
Updated for the changes in 1.6:

simple lists from JSON can now be read by single attribute records. The "Value" attribute is only used for disambiguation if the record has more than one attribute.

JSON Select now un-wraps string values, making it more useful. It also doesn't throw errors when the path is not found (returns empty string). This should avoid some of the cumbersomeness in its use. It also means you should probably double-check your code if you plan on using this.
Hi Ricardo - Trying to Serialize DateTime records that are in 24-hr format and running into an issue where the times after 12:00 translate to AM times.  For instance, 23:00 becomes 11:00.  Any thoughts?

Hello Doug,

Please see my answer in this post. I would like to reiterate my request to not use this thread to report bugs. If you want to report a bug, please open a new thread.

Best regards,
Ricardo Silva