Skip to content
Sean Leary edited this page Sep 2, 2023 · 13 revisions

Welcome to the JSON-java wiki

Introduction

JSON-Java is a reference application for reading and writing JSON docs in Java. It was written by Douglas Crockford, who first specified the JSON document format. It works by parsing and storing JSON text inside of POJOs - Plain Old Java Objects. This allows your Java code to navigate into the doc, read, update, and write the JSON document.

Quick Start

The primary purpose of this project is to show how to parse and emit JSON documents in Java. There are two primary classes:

  • JSONObject: Parse a JSON object from a String, update the JSON, and emit it as a String.
  • JSONArray: Parse a JSON array from a String, update the JSON, and emit it as a String.

Parsing JSON documents

For the purposes of this project, a JSON doc is a valid JSON text string that begins with '{' or '['. JSON text that consists entirely of a string or primitive type is represented by the corresponding Java type and is not parsed or emitted by this library. If the text string begins with '{', it should be parsed by creating a new JSONObject(String). If the text begins with '[', it should be parsed by creating a new JSONArray(String).

Other ways to create JSON classes

  • Create a new JSONObject() and populate the instance by calling put*(), putOpt*(), append(), and accumulate() API methods.
  • Create a new JSONArray() and populate the instance by calling put*(), putOpt*(), putAll(), and addAll() API methods.
  • JSON text that is accessed via a Reader object can be parsed with a JSONTokener. Here is an example using a JSONObject. The reader should be closed by the calling code after the JSONObject is created.
        Reader reader;
        /* initialize the reader */
        JSONObject jsonObject = new JSONObject(new JSONTokener(reader));

Emitting JSON documents

Calling jsonObject.toString() or jsonArray.toString() will cause the instance to emit its contents as a syntactically correct JSON document without blank-space chars. An empty JSONObject will emit "{}". An empty JSONArray will emit "[]". Formatted output can be obtained by calling jsonObject.toString(int) or jsonArray.toString(int), where the int parameter indicates the indentation.

Parsing XML Using org.json.XML and XMLParserConfiguration Java Classes

Overview

Parsing and converting XML (eXtensible Markup Language) data to JSON (JavaScript Object Notation) in Java is often necessary when dealing with legacy APIs, configuration files, or data formats. This section offers a comprehensive look into how to accomplish this task using the org.json.XML and XMLParserConfiguration classes in the JSON-java library.

XML and JSON are inherently different formats, each with their unique features and limitations. For instance, XML supports attributes, complex nesting, and a broad array of data types, while JSON offers a simpler, more streamlined data format. This discrepancy poses several challenges in data conversion.

Transforming XML (eXtensible Markup Language) to JSON (JavaScript Object Notation) can be problematic due to several key differences between the two data formats. Here are some of the main issues that can arise during the conversion:

  1. Complexity in XML: XML can represent complex, hierarchical data structures with the use of attributes, nested elements, and namespaces. JSON, while it can also represent nested structures, lacks the same degree of complexity. There's no direct equivalent for attributes or namespaces in JSON. As a result, transforming XML that heavily uses these features into JSON can lead to a loss of information or lead to convoluted JSON structures.

  2. Order of Elements: In XML, the order of elements can be significant. For instance, in an XML document representing a book, the order of chapters would be important. However, JSON is primarily based on unordered sets of name/value pairs. While arrays in JSON preserve order, interpreting when to use arrays during the transformation from XML can be an issue.

  3. Text and Mixed Content: XML supports mixed content (elements with both text and child elements), while JSON does not have a built-in mechanism for representing this kind of data. This discrepancy can make certain XML documents difficult to representin JSON.

  4. Metadata and Schemas: XML has built-in support for schemas (like XML Schema or DTD), which can provide detailed rules about what data an XML document can contain and how it should be structured. JSON lacks a similar, universally accepted schema language. Metadata that's part of the XML document (like namespaces, comments, and processing instructions) might be lost in the conversion to JSON, as JSON doesn't have built-in equivalents for these constructs.

  5. Attributes and Namespaces: In XML, elements can have attributes and namespaces, but in JSON, there are no equivalent concepts. This discrepancy can cause a loss of information in the conversion process. Various conversion algorithms handle this differently, such as converting attributes to name/value pairs, but this can create more complex and less intuitive JSON structures.

  6. Data Types: XML data is mostly text, while JSON provides more explicit and diverse data types like Boolean, Number, and Null in addition to String. When converting from XML to JSON, you may need to infer the correct data type, which is not always straightforward.

XML to JSON Conversion Basics

The org.json.XML class provides a straightforward way to convert XML data into a JSON object. Below is a simple example:

import org.json.XML;
import org.json.JSONObject;

public class Main {
    public static void main(String[] args) {
        String xmlString = "<book><title>The Catcher in the Rye</title><author>J.D. Salinger</author></book>";
        JSONObject jsonObject = XML.toJSONObject(xmlString);
        System.out.println(jsonObject.toString(2));
    }
}

Customizing XML Parser Configuration

The XMLParserConfiguration class allows you to customize how the XML parser behaves. Here's how to use it:

Creating an Instance

You can create an XMLParserConfiguration instance with your preferred settings. For example, to preserve all numerical strings as is, set keepStrings to true:

XMLParserConfiguration config = new XMLParserConfiguration().withKeepStrings(true);

Applying the Configuration

Use the toJSONObject method and pass your XMLParserConfiguration instance:

JSONObject jsonObject = XML.toJSONObject(xmlString, config);

Example: Difference in Configuration

Consider the following XML string:

<person age="30">John Doe</person>

Here's how the conversion will differ based on the keepStrings setting.

  • Without Custom Configuration

    JSONObject jsonObject = XML.toJSONObject("<person age=\"30\">John Doe</person>");
    System.out.println(jsonObject.toString());

    Output:

    {"person": {"age": 30, "content": "John Doe"}}

    Notice that the "age" attribute is converted to a number.

  • With Custom Configuration

    XMLParserConfiguration config = new XMLParserConfiguration(true);
    JSONObject jsonObject = XML.toJSONObject("<person age=\"30\">John Doe</person>", config);
    System.out.println(jsonObject.toString());

    Output:

    {"person": {"age": "30", "content": "John Doe"}}

    In this case, "age" is preserved as a string.

XMLParserConfiguration in Depth

Each XMLParserConfiguration property provides a different way to customize the parser. Attach a property value to the constructor by using 'fluent setter' methods, which can be concatenated together with the constructor, e.g. new XMLParserConfiguration().withKeepStrings(true).withcDataTagName("MyCDATA").

  • withKeepStrings(boolean): If true, values will not be attempted to be converted to a number, boolean, or null.

  • withcDataTagName(String): If not null and not the empty string, this is the name of the XML tag that will be used to store the content of tags that contain CDATA sections.

  • withConvertNilAttributeToNull(boolean): If true, and the nil attribute of a tag is set to true, the value of the tag will be set to a JSONNull object.

  • withXsiTypeMap(Map<String, XMLXsiTypeConverter<?>>): Specifies that the values with attribute xsi:type will be converted to a target type defined in the map.

  • withForceList(Set): Tags listed in the set are converted to JSONArray list entries

Handling Parsing Errors

  • withMaxNestingDepth(int): Defines the maximum nesting depth the parser will descend before throwing an exception. The default is 512.