Generate Document from JSON Data Source

Overview

GroupDocs.Assembly for Python via .NET enables you to generate documents directly from JSON data sources. The JsonDataSource class parses JSON and makes it available to your templates, supporting both simple and complex JSON structures.

The main classes involved are:

Here are the steps to generate documents from JSON:

  • Create or obtain JSON data (from a file, an API response, or a string)
  • Instantiate JsonDataSource with the JSON file’s path, or with a binary stream holding the JSON text
  • Create a template document with expression tags referencing JSON properties
  • Use DocumentAssembler to assemble the template with JsonDataSource
  • Save the assembled document
Note
JsonDataSource automatically recognizes JSON types (numbers, booleans, dates, strings) and makes them available with proper types in templates, enabling numeric operations and date formatting. You can also read JSON with Python’s json module and pass the resulting dicts and lists, as shown in Generate from Custom Objects; then the JSON’s strings stay strings, and a date must be turned into a datetime in Python.

Generate Document from JSON File

The simplest way to use JSON data is from a file:

from groupdocs.assembly import DataSourceInfo, DocumentAssembler
from groupdocs.assembly.data import JsonDataSource

json_data_source = JsonDataSource("staff-member.json")

assembler = DocumentAssembler()
assembler.assemble_document("staff-member-card.docx", "staff-member-card-report.docx",
                            DataSourceInfo(json_data_source, "data"))

The following sample file is used in this example: staff-member.json

The following sample file is used in this example: staff-member-card.docx

Binary file (DOCX, 7 KB)

Download full output

Generate Document from JSON String

JsonDataSource reads a file path or a stream, and a str is always taken as a path. To use JSON text you already hold in memory, wrap its UTF-8 bytes in io.BytesIO:

import io

from groupdocs.assembly import DataSourceInfo, DocumentAssembler
from groupdocs.assembly.data import JsonDataSource

json_string = """{
    "name": "Jonas Weber",
    "age": 37,
    "email": "jonas.weber@harborlane.example",
    "active": true
}"""

json_data_source = JsonDataSource(io.BytesIO(json_string.encode("utf-8")))

assembler = DocumentAssembler()
assembler.assemble_document("staff-member-card.docx", "staff-member-card-from-string.docx",
                            DataSourceInfo(json_data_source, "data"))

The following sample file is used in this example: staff-member-card.docx

Binary file (DOCX, 7 KB)

Download full output

Working with JSON Arrays

When your JSON root is an array, JsonDataSource treats it as a collection:

import io

from groupdocs.assembly import DataSourceInfo, DocumentAssembler
from groupdocs.assembly.data import JsonDataSource

json_array = """[
    { "name": "Amara Osei", "age": 41 },
    { "name": "Jonas Weber", "age": 37 },
    { "name": "Lena Park", "age": 29 }
]"""

json_data_source = JsonDataSource(io.BytesIO(json_array.encode("utf-8")))

assembler = DocumentAssembler()
assembler.assemble_document("staff-list.docx", "staff-list-report.docx",
                            DataSourceInfo(json_data_source, "people"))

The following sample file is used in this example: staff-list.docx

Binary file (DOCX, 7 KB)

Download full output

Template Example for JSON Object

For a JSON object like {"name": "Amara Osei", "age": 41}, your template can reference properties directly:

Name: <<[data.name]>>
Age: <<[data.age]>>

Template Example for JSON Array

For a JSON array, use a foreach data band to iterate:

<<foreach [in people]>>
Name: <<[name]>>, Age: <<[age]>>
<</foreach>>

Working with Nested JSON Objects

JsonDataSource handles nested JSON structures automatically:

import io

from groupdocs.assembly import DataSourceInfo, DocumentAssembler
from groupdocs.assembly.data import JsonDataSource

nested_json = """{
    "company": "Harbor Lane Provisions",
    "address": {
        "street": "18 Quayside Road",
        "city": "Port Ellery",
        "zip": "48210"
    },
    "employees": [
        { "name": "Amara Osei", "position": "Operations Director" },
        { "name": "Mei Tanaka", "position": "Account Manager" }
    ]
}"""

json_data_source = JsonDataSource(io.BytesIO(nested_json.encode("utf-8")))

assembler = DocumentAssembler()
assembler.assemble_document("company-profile.docx", "company-profile-report.docx",
                            DataSourceInfo(json_data_source, "company"))

The following sample file is used in this example: company-profile.docx

Binary file (DOCX, 8 KB)

Download full output

Template for nested JSON:

Company: <<[company.company]>>
Address: <<[company.address.street]>>, <<[company.address.city]>> <<[company.address.zip]>>

Employees:
<<foreach [in company.employees]>>
- <<[name]>>, <<[position]>>
<</foreach>>

Configure JSON Data Load Options

You can configure how JsonDataSource parses JSON. The file below has one root property, accounts, holding an array, and account codes with leading zeros:

from groupdocs.assembly import DataSourceInfo, DocumentAssembler
from groupdocs.assembly.data import JsonDataLoadOptions, JsonDataSource, JsonSimpleValueParseMode

options = JsonDataLoadOptions()
options.always_generate_root_object = True  # Always create root object
options.simple_value_parse_mode = JsonSimpleValueParseMode.STRICT  # Strict type parsing

json_data_source = JsonDataSource("trade-accounts.json", options)

assembler = DocumentAssembler()
assembler.assemble_document("trade-account-list.docx", "trade-account-list-report.docx",
                            DataSourceInfo(json_data_source, "data"))

The following sample file is used in this example: trade-accounts.json

The following sample file is used in this example: trade-account-list.docx

Binary file (DOCX, 7 KB)

Download full output

The template reaches the array through the root object:

<<foreach [in data.accounts]>>
<<[name]>> (account <<[code]>>), managed by <<[manager]>>
<</foreach>>

With JsonSimpleValueParseMode.STRICT, a JSON string stays a string, so the account code "0142" is written as 0142. In the default LOOSE mode, a string that looks like a number becomes a number, and the same tag writes 142.

Warning
By default, if a root JSON element is an object with only one property that is an object or array, the engine skips the root object. Set always_generate_root_object to True to always include it. Without it, data above is the array itself, and data.accounts fails with “Can not get the value of member ‘accounts’”.

Advanced Usage Topics

To learn more about working with complex JSON structures, date-time parsing, and advanced JsonDataSource options, please refer to the advanced usage section.

More resources

GitHub Examples

You may easily run the code above and see the feature in action in our GitHub examples:

Free Online Apps

Along with the full-featured library, we provide simple but powerful free online apps.

To assemble documents from templates and data sources, you can use the online apps from the GroupDocs.Assembly App Product Family.

Close
Loading

Analyzing your prompt, please hold on...

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