Working with JSON Data Sources

Simplified working with JSON data sources

To access JSON data while building a report, pass a JsonDataSource instance to the assembler as a data source. A JsonDataSource can be created from a file path or from a Java InputStream, optionally with JsonDataLoadOptions.

Using JsonDataSource enables you to work with typed values of JSON elements in template documents. For more convenience, the set of simple JSON types is extended as follows:

  • Integer
  • Long
  • Double
  • Boolean
  • Date
  • String

Treating top-level arrays or objects having an array

In template documents, if a top-level JSON element is an array or an object having only one property of an array type, a JsonDataSource instance should be treated in the same way as if it was a DataTable instance (see “Using Data Sources” for more information) as shown in the following example.

Suppose we have JSON data like:

[
   {
      Name:"John Doe",
      Age:30,
      Birth:"1989-04-01 4:00:00 pm"
   },
   {
      Name:"Jane Doe",
      Age:27,
      Birth:"1992-01-31 07:00:00 am"
   },
   {
      Name:"John Smith",
      Age:51,
      Birth:"1968-03-08 1:00:00 pm"
   }
]

or alternative JSON like:

{
   Persons:[
      {
         Name:"John Doe",
         Age:30,
         Birth:"1989-04-01 4:00:00 pm"
      },
      {
         Name:"Jane Doe",
         Age:27,
         Birth:"1992-01-31 07:00:00 am"
      },
      {
         Name:"John Smith",
         Age:51,
         Birth:"1968-03-08 1:00:00 pm"
      }
   ]
}

And the following template:

<<foreach [in persons]>>Name: <<[Name]>>, Age: <<[Age]>>, Date of Birth: <<[Birth]:"dd.MM.yyyy">>
<</foreach>>
Average age: <<[persons.average(p => p.Age)]>>

The data source is passed under the name used in the template:

const groupdocs = require('@groupdocs/groupdocs.assembly');

const dataSource = new groupdocs.JsonDataSource("persons.json");
const assembler = new groupdocs.DocumentAssembler();
assembler.assembleDocument("template.txt", "report.txt",
    new groupdocs.DataSourceInfo(dataSource, "persons"));

For both pieces of JSON data, the result is:

Name: John Doe, Age: 30, Date of Birth: 01.04.1989
Name: Jane Doe, Age: 27, Date of Birth: 31.01.1992
Name: John Smith, Age: 51, Date of Birth: 08.03.1968

Average age: 36.0
Warning
Using a custom date-time format is possible because text values of the Birth properties are automatically converted to dates.

Treating objects at the top level

If a top-level JSON element represents an object, a JsonDataSource instance should be treated in template documents in the same way as if it was a DataRow instance (see “Using Data Sources” for more information). If a top-level JSON object has a single property that is also an object, then this nested object is accessed by the assembler instead. To see how it works, consider the following example.

Suppose we have JSON data like:

{
   Name:"John Doe",
   Age:30,
   Birth:"1989-04-01 4:00:00 pm",
   Child:[
      "Ann Doe",
      "Charles Doe"
   ]
}

or alternatively like:

{
   Person:{
      Name:"John Doe",
      Age:30,
      Birth:"1989-04-01 4:00:00 pm",
      Child:[
         "Ann Doe",
         "Charles Doe"
      ]
   }
}

And the following template, where members of the object are referenced directly:

Name: <<[Name]>>, Age: <<[Age]>>, Date of Birth:
<<[Birth]:"dd.MM.yyyy">>
Children:
<<foreach [in Child]>><<[Child_Text]>>
<</foreach>>

In this case, the data source can be passed without a name:

const dataSource = new groupdocs.JsonDataSource("person.json");
assembler.assembleDocument("template.txt", "report.txt",
    new groupdocs.DataSourceInfo(dataSource));

For both pieces of JSON data, the result is:

Name: John Doe, Age: 30, Date of Birth:
01.04.1989
Children:
Ann Doe
Charles Doe
Warning
To reference a JSON object property that is an array of simple-type values, use the name of the property (for example, “Child”) in a template document, and the same name with the “_Text” suffix (for example, “Child_Text”) to reference the value of an item of this array.

The complete example

The following example sums up typical scenarios involving nested JSON objects and arrays.

JSON

[
   {
      Name:"John Smith",
      Contract:[
         {
            Client:{
               Name:"A Company"
            },
            Price:1200000
         },
         {
            Client:{
               Name:"B Ltd."
            },
            Price:750000
         },
         {
            Client:{
               Name:"C & D"
            },
            Price:350000
         }
      ]
   },
   {
      Name:"Tony Anderson",
      Contract:[
         {
            Client:{
               Name:"E Corp."
            },
            Price:650000
         },
         {
            Client:{
               Name:"F & Partners"
            },
            Price:550000
         }
      ]
   },
   {
      Name:"July James",
      Contract:[
         {
            Client:{
               Name:"G & Co."
            },
            Price:350000
         },
         {
            Client:{
               Name:"H Group"
            },
            Price:250000
         },
         {
            Client:{
               Name:"I & Sons"
            },
            Price:100000
         },
         {
            Client:{
               Name:"J Ent."
            },
            Price:100000
         }
      ]
   }
]

Template document

<<foreach [in managers]>>Manager: <<[Name]>>
Contracts:
<<foreach [in Contract]>>- <<[Client.Name]>> ($<<[Price]>>)
<</foreach>>
<</foreach>>

Source code

const groupdocs = require('@groupdocs/groupdocs.assembly');

// Source template and destination report
const templatePath = "SimpleDatasetDemo.docx";
const reportPath = "SimpleJsonDSDemo Out.docx";

// Load the JSON data
const dataSource = new groupdocs.JsonDataSource("ManagerData.json");
const dataSourceInfo = new groupdocs.DataSourceInfo(dataSource, "managers");

// Assemble the document
const assembler = new groupdocs.DocumentAssembler();
assembler.assembleDocument(templatePath, reportPath, dataSourceInfo);

process.exit(0);

Result document

Manager: John Smith
Contracts:
- A Company ($1200000)
- B Ltd. ($750000)
- C & D ($350000)
Manager: Tony Anderson
Contracts:
- E Corp. ($650000)
- F & Partners ($550000)
Manager: July James
Contracts:
- G & Co. ($350000)
- H Group ($250000)
- I & Sons ($100000)
- J Ent. ($100000)

Recognition of JSON simple values

For recognition of JSON simple values (null, boolean, number, integer, and string), the engine provides two modes: loose and strict. In the loose mode, types of JSON simple values are determined upon parsing of their string representations. In the strict mode, types of JSON simple values are determined from JSON notation itself. To see the main difference between the modes, consider the following JSON snippet.

{ prop: "123" }

In the loose mode, the type of prop is determined as integer, whereas in the strict mode, it is determined as string.

The loose mode is used by default to support more typed data representation options. However, in some scenarios it is preferable to disable recognition of numbers and other JSON simple values from strings, for example, when you need to keep leading padding zeros in a string value representing a number. In this case, switch to the strict mode as shown in the following code snippet.

const options = new groupdocs.JsonDataLoadOptions();
options.setSimpleValueParseMode(groupdocs.JsonSimpleValueParseMode.STRICT);
const dataSource = new groupdocs.JsonDataSource("data.json", options);

Note – Parsing of date-time values does not depend on whether the loose or strict mode is used.

Recognition of date-time values is a special case, because the JSON specification does not define a format for their representation. So, by default, while parsing date-time values from strings, the engine tries several formats in the following order:

  1. The ISO-8601 format (for values like “2015-03-02T13:56:04Z”)
  2. The Microsoft® JSON date-time format (for values like “/Date(1224043200000)/”)
  3. All date-time formats supported for the current culture
  4. All date-time formats supported for the English USA culture
  5. All date-time formats supported for the English New Zealand culture

Although this approach is quite flexible, in some scenarios you may need to restrict which strings are recognized as date-time values. You can achieve this by specifying an exact format, in the context of the current culture (the JVM default locale), to be used while parsing date-time values from strings as shown in the following example.

const options = new groupdocs.JsonDataLoadOptions();
options.setExactDateTimeParseFormat("MM/dd/yyyy");
const dataSource = new groupdocs.JsonDataSource("data.json", options);

In this example, strings conforming to the format “MM/dd/yyyy” are recognized as date-time values while loading JSON, whereas the others are not (but see the following note).

In some scenarios, you may need to disable recognition of date-time values at all, for example, when you deal with strings containing already formatted date-time values, which you do not want to re-format using the engine. You can achieve this by setting the exact date-time parse format to an empty string (but see the following note).

Note – Strings conforming to the Microsoft® JSON date-time format (for example, “/Date(1224043200000)/”) are always recognized as date-time values regardless of the exact date-time parse format.

Download

Data source document

Template

Close
Loading

Analyzing your prompt, please hold on...

An error occurred while retrieving the results. Please refresh the page and try again.