# JSON and XML

> Merge JSON strings and XML files in a WPF application: MergeJsonData, ParserException, relations from DataSet.ReadXml, parsing cultures and LoadJson.

- **Product:** TX Text Control .NET for WPF
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for WPF > Mail Merge and Reporting > Data Sources > JSON and XML
- **2966 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/json-xml/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/json-xml/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/json-xml/llms-full.txt

---

Data that arrives as text needs no classes in your application: a JSON string from a web service goes straight into `MailMerge`, and an XML file takes one extra step through a `DataSet`. This applies whether the WPF application receives the data, reads it from disk or lets users open a file in the **Reporting** tab. The sections below give the rules of each format, the exceptions for invalid JSON and the cultures that parse numbers and dates written as text.

The examples use *invoice.json* of the Getting Started tutorial [Create a Template](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/mail-merge/template/llms-full.txt) and a window with a `TextControl` named `textControl1` that shows the template *invoice.docx*.

### Merge JSON Data

[MergeJsonData](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/mergejsondata-method/llms-full.txt) takes the JSON as a string and analyzes it like [MergeObjects](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/mergeobjects-method/llms-full.txt) analyzes objects:

- **One object or an array.** The JSON holds a single object or an array of objects with the same structure, and the template is merged once per object.
- **The first object defines the structure.** Tables, columns and relations come from the property names and nested objects of the object, or of the first object in the array.
- **Nested objects and arrays.** A nested object provides values for fields with dot notation, such as `Customer.City`, and an array the records of the merge block with its name, such as `Items`.
- **Images.** An image placeholder can receive an image given as a Base64 string, as [Images and Barcodes](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/images-barcodes/llms-full.txt) describes.

Invalid JSON makes `MergeJsonData` throw an exception derived from [ParserException](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-json/parserexception/llms-full.txt) in the `TXTextControl.DocumentServer.Json` namespace:

| Exception | Cause |
|---|---|
| [UnexpectedEndOfInputException](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-json/unexpectedendofinputexception/llms-full.txt) | The JSON string is incomplete |
| [UnexpectedTokenException](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-json/unexpectedtokenexception/llms-full.txt) | The JSON contains an unexpected character |
| [InvalidNumberFormatException](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-json/invalidnumberformatexception/llms-full.txt) | A number has an invalid format |
| [InvalidCodePointException](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-json/invalidcodepointexception/llms-full.txt) | A hexadecimal Unicode code point is invalid |
| [UnknownLiteralNameTokenException](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-json/unknownliteralnametokenexception/llms-full.txt) | An unknown character sequence stands where `true`, `false` or `null` is expected |
| [UnknownParseErrorException](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-json/unknownparseerrorexception/llms-full.txt) | The parser encountered another error |

Catching the base class handles every case. In a button's `Click` handler in *MainWindow.xaml.cs*:

```csharp
using System.IO;
using System.Windows;
using TXTextControl.DocumentServer;
using TXTextControl.DocumentServer.Json;
```

```csharp
private void mergeJsonButton_Click(object sender, RoutedEventArgs e)
{
    using (MailMerge mailMerge = new MailMerge { TextComponent = textControl1 })
    {
        try
        {
            mailMerge.MergeJsonData(File.ReadAllText("invoice.json"));
        }
        catch (ParserException exception)
        {
            MessageBox.Show(this, $"Invalid JSON ({exception.GetType().Name}): {exception.Message}");
        }
    }
}
```

With valid data, the editor shows the merged invoice. Remove a closing bracket from *invoice.json* to see the message with the name of the exception.

### Merge XML Data

XML goes through a `DataSet`: `DataSet.ReadXml` reads the file, and [Merge](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/merge-method/llms-full.txt) merges its master table, as for any [DataSet](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/datasets/llms-full.txt). The invoice as *invoice.xml*, copied to the output folder:

```xml
<?xml version="1.0" encoding="utf-8"?>
<Invoices>
  <Invoice>
    <Company>Contoso Ltd.</Company>
    <Name>Jane Miller</Name>
    <InvoiceNumber>INV-1001</InvoiceNumber>
    <Items>
      <Description>Consulting</Description>
      <Quantity>2</Quantity>
      <Price>150.00</Price>
    </Items>
    <Items>
      <Description>Training</Description>
      <Quantity>1</Quantity>
      <Price>480.00</Price>
    </Items>
  </Invoice>
</Invoices>
```

From the repeated elements, `ReadXml` creates the tables `Invoice` and `Items`. Because `Items` is nested in `Invoice`, it adds a key column `Invoice_Id` to both and a relation between them, which gives the `Items` block the items of each invoice:

```csharp
using System.Data;
using System.Globalization;
using System.Windows;
using TXTextControl.DocumentServer;
```

```csharp
private void mergeXmlButton_Click(object sender, RoutedEventArgs e)
{
    // Nested elements become related tables
    DataSet dataSet = new DataSet();
    dataSet.ReadXml("invoice.xml");

    using (MailMerge mailMerge = new MailMerge
    {
        TextComponent = textControl1,
        // The prices in the XML file are written the US English way
        DataSourceCulture = CultureInfo.GetCultureInfo("en-US")
    })
    {
        mailMerge.Merge(dataSet.Tables["Invoice"], true);
    }
}
```

Flat XML, whose tables are linked by key columns instead of nesting, needs relations added after `ReadXml`, as [DataSets and DataTables](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/datasets/#merge-related-tables) shows. Microsoft's [Inferring Relationships](https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/dataset-datatable-dataview/inferring-relationships) documents how `ReadXml` derives relations.

### Parse Numbers and Dates With the Right Culture

Without a schema, `ReadXml` reads every value as a string, and JSON often carries dates as strings. `MailMerge` parses numbers and dates from the data with the culture in [DataSourceCulture](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/datasourceculture-property/llms-full.txt) and formats them in the document with the culture in [MergeCulture](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/mergeculture-property/llms-full.txt). Both default to the culture of the current thread, which follows the regional settings of the user's Windows account, so the same file can merge differently on two computers. Set them explicitly when the data has a fixed format:

```csharp
mailMerge.DataSourceCulture = new CultureInfo("de-DE");   // how the data writes numbers
mailMerge.MergeCulture = new CultureInfo("en-US");        // how the document shows them
```

The properties must be set before the merge method is called. [Merge Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/fields/llms-full.txt) describes the same two properties for a single field.

### Load JSON and XML Into the Reporting Tab

In the **Select Data Source** drop-down of the WPF Reporting tab, **Load XML File** and **Load JSON File** let users open a data file for template design; [Data Sources](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/#data-sources-in-the-reporting-tab) shows the drop-down. In code, the [DataSourceManager](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/ribbonreportingtab/datasourcemanager-property/llms-full.txt) of the tab loads the same data: [LoadJson](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-datasources/datasourcemanager/loadjson-method/llms-full.txt) a JSON string, [LoadXmlFile](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-datasources/datasourcemanager/loadxmlfile-method/llms-full.txt) an XML file and [LoadXmlString](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-datasources/datasourcemanager/loadxmlstring-method/llms-full.txt) XML as a string. Connect the handler with `Loaded="textControl1_Loaded"` on the `TextControl` element:

```csharp
private void textControl1_Loaded(object sender, RoutedEventArgs e)
{
    ribbonReportingTab1.DataSourceManager.LoadXmlFile("invoice.xml");
}
```

A few records with the structure of the real data fill the drop-downs. The template designed with them merges with any data of that structure, as JSON, XML, objects or a `DataSet`.

### Next Steps

- [Objects and Collections](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/objects/llms-full.txt): the rules `MergeJsonData` shares with business objects.
- [DataSets and DataTables](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/datasets/llms-full.txt): relations for flat tables.
- [Merge Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/fields/llms-full.txt): numeric and date formats of single fields.
- [Merge Blocks](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/blocks/llms-full.txt): the blocks that arrays fill.
- The blog article [MailMerge: Data Structures Explained with a Sample Template and JSON Data](https://www.textcontrol.com/blog/2022/03/14/mailmerge-data-structures-explained-with-a-sample-template-and-json-data/): nested JSON data and the template it fills.

---

## Nearby

- **Previous:** [DataSets and DataTables](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/datasets/llms-full.txt)
- **Next:** [Data Source Configuration Files](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/configuration-files/llms-full.txt)
