Getting Started with JSON

Requirements: IP*Works!

Introduction

The JSON component offers a fast and simple way to parse and extract information from JSON documents. This guide covers the various ways in which data can be accessed after parsing.

Contents

Overview

The JSON component parses JSON documents and verifies that they are well-formed. The results are provided through a set of events.

In addition, the document structure may be queried through an XPath mechanism that supports a subset of the XPath and JSONPath specification.

The parser is optimized for read applications, with a very fast engine that builds internal DOM structures with close to zero heap allocations. Additionally, BuildDOM can be set to False which reduces the overhead of creating the DOM and offers a fast forward-only parsing implementation which fires events to provide the parsed data.

When parsing a document events will fire to provide information about the parsed data. After Parse returns the document may be navigated by setting XPath if BuildDOM is set to True (default). If BuildDOM is False parsed data is only accessible through the events.

The following events will fire during parsing:

  • StartElement
  • Characters
  • EndElement
  • IgnorableWhitespace

Input Properties

The component will determine the source of the input based on which properties are set.

The order in which the input properties are checked is as follows:

  • SetInputStream (.NET and Java Only)
  • InputFile
  • InputData
When a valid source is found the search stops.

If parsing multiple documents call Reset between documents to reset the parser.

XPath

If BuildDOM is set to True (default), XPath may be set after Parse.

XPath may be set to navigate to specific elements within the JSON document. This will be the path to a specified value within the document. Since arrays in JSON only contain values, and no associated object name, an empty name will be used for these values. To reach an array element at position 1, the path must be set to "[1]". In addition, a root element named "json" will be added to each JSON document in the parser.

BuildDOM must be set to True prior to parsing the document for the XPath functionality to be available.

The XPath property accepts both XPath and JSONPath formats. Please see notes below on both formats.

XPath

The path is a series of one or more element accessors separated by '/'. The path can be absolute (starting with '/') or relative to the current XPath location.

The following are possible values for an element accessor:

AccessorDescription
'name'A particular element name.
[i]The i-th subelement of the current element.
..the parent of the current element.

When XPath is set to a valid path the following properties are updated:

  • XElement
  • XElementType
  • XParent
  • XText
  • XSubTree
  • XChildren

BuildDOM must be set to True prior to parsing the document for the XPath functionality to be available.

Simple JSON document

{
  "firstlevel": {
    "one": "value",
    "two": ["first", "second"],
    "three": "value three"
  }
}
Example (Setting XPath):

Document root JsonControl.XPath = "/"
Specific Element JsonControl.XPath = "/json/firstlevel/one/"
i-th Child JsonControl.XPath = "/json/firstlevel/two/[i]/"
Note: When using XPath notation the root element is always referred to as "json". As in the above examples this means all paths will begin with "/json".

JSONPath

If BuildDOM is set to True (default), XPath may be set after Parse.

JSONPath

The XPath property implements a subset of the JSONPath notation. This may be set to point to a specific element in the JSON document.

The JSONPath is a series of one or more accessors in either dot-notation\

$.store.book[0].title

Or bracket-notation

$['store']['book'][0]['title']

After setting XPath the following properties are populated:

  • XChildren
  • XElement
  • XElementType
  • XSubTree
  • XText

Examples

Given the following JSON document:

{
    "store": {
        "book": [
            {
                "category": "reference",
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "price": 8.95
            },
            {
                "category": "fiction",
                "author": "Evelyn Waugh",
                "title": "Sword of Honour",
                "price": 12.99
            },
            {
                "category": "fiction",
                "author": "Herman Melville",
                "title": "Moby Dick",
                "isbn": "0-553-21311-3",
                "price": 8.99
            },
            {
                "category": "fiction",
                "author": "J. R. R. Tolkien",
                "title": "The Lord of the Rings",
                "isbn": "0-395-19395-8",
                "price": 22.99
            }
        ],
        "bicycle": {
            "color": "red",
            "price": 19.95
        }
    },
}

The following code shows several examples.

Get the first book's author:

json.XPath = "$.store.book[0].author";
Console.WriteLine(json.XText);

Outputs:

"Nigel Rees"

Select the first book and inspect the children:

json.XPath = "$.store.book[0]";
Console.WriteLine("Child Count: " + json.XChildren.Count);
Console.WriteLine(json.XChildren[1].Name + ": " + json.XChildren[1].XText);

Outputs:

Child Count: 4
author: "Nigel Rees"

Get the price of the second book:

json.XPath = "$['store']['book'][1]['price']";
Console.WriteLine(json.XText);

Outputs:

12.99

Get the second to last book's author:

json.XPath = "$['store']['book'][last() - 1]['author']";
Console.WriteLine(json.XText);
Console.WriteLine(json.XPath); //Note that "last() - 1" is resolved to "3".

Outputs:

"Herman Melville"
$['store']['book'][3]['author']

Display the full subtree at the current path:

json.XPath = "$.store.book[0]";
Console.WriteLine(json.XSubTree);

Outputs:

{
    "category": "reference",
    "author": "Nigel Rees",
    "title": "Sayings of the Century",
    "price": 8.95
}

Forward-Only

The component can optionally be used in a forward-only mode which further reduces the overhead and increases performance since building a DOM is not necessary. To enable this mode set BuildDOM to False before calling Parse. When Parse is called data will be available through the events. For instance, using the same example above the code:

Json json = new Json();
json.BuildDOM = false; //Forward-Only
json.OnStartElement += Json_OnStartElement;
json.OnEndElement += Json_OnEndElement;
json.OnCharacters += Json_OnCharacters;
json.InputData = input;
json.Parse();

//Events defined in another section of the application:
private static void Json_OnCharacters(object sender, JsonCharactersEventArgs e)
{
  Console.WriteLine("Characters: " + e.Text);
}

private static void Json_OnEndElement(object sender, JsonEndElementEventArgs e)
{
  Console.WriteLine("End Element: " + e.Element);
}

private static void Json_OnStartElement(object sender, JsonStartElementEventArgs e)
{
  Console.WriteLine("Start Element: " + e.Element);
}

Will output data through events, resulting in output like below. Note that this is truncated here for readability.

Start Element: json
Start Element: store
Start Element: book
Start Element: 
Start Element: category
Characters: "reference"
End Element: category
Start Element: author
Characters: "Nigel Rees"
End Element: author
Start Element: title
Characters: "Sayings of the Century"
End Element: title
...

We appreciate your feedback.  If you have any questions, comments, or suggestions about this article please contact our support team at kb@nsoftware.com.