Converting XML to JSON - beckchr/staxon GitHub Wiki

There are two well known and simple ways to copy XML

  • Use XSLT with default templates (identity transform)
  • Use the StAX event API to copy all events from a reader to a writer

Let's see how we can use StAXON to convert XML to JSON using either of those techniques.

Consider the following XML sample:

input.xml

<?xml version="1.0"?>
<customer>
	<first-name>Jane</first-name>
	<last-name>Doe</last-name>
	<address>
		<street>123 A Street</street>
	</address>
	<phone-number type="work">555-1111</phone-number>
	<phone-number type="cell">555-2222</phone-number>
</customer>

With StAXON's Mapping Convention, attributes are mapped to fields prefixed with "@" and text content for an element which is mapped to JSON objects (i.e. an element with attributes or namespace declarations) is mapped to a "$" field.

Therefore, converting the above to JSON yields

output.json

{
  "customer" : {
    "first-name" : "Jane",
    "last-name" : "Doe",
    "address" : {
      "street" : "123 A Street"
    },
    "phone-number" : [ {
      "@type" : "work",
      "$" : "555-1111"
    }, {
      "@type" : "cell",
      "$" : "555-2222"
    } ]
  }
}

Here's the code...

Copying XML to JSON via XSL Transformation

package de.odysseus.staxon.sample.copy;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stax.StAXResult;
import javax.xml.transform.stax.StAXSource;

import de.odysseus.staxon.json.JsonXMLConfig;
import de.odysseus.staxon.json.JsonXMLConfigBuilder;
import de.odysseus.staxon.json.JsonXMLOutputFactory;

public class XML2JSON1 {
	/**
	 * Copy/format XML as JSON using {@link Transformer#transform(Source, Result)}.
	 * @param args ignored
	 * @throws TransformerException
	 * @throws XMLStreamException
	 */
	public static void main(String[] args) throws TransformerException, XMLStreamException, IOException {
		InputStream input = XML2JSON1.class.getResourceAsStream("input.xml");
		OutputStream output = System.out;
		/*
		 * If we want to insert JSON array boundaries for multiple elements,
		 * we need to set the <code>autoArray</code> property.
		 * If our XML source was decorated with <code>&lt;?xml-multiple?&gt;</code>
		 * processing instructions, we'd set the <code>multiplePI</code>
		 * property instead.
		 * With the <code>autoPrimitive</code> property set, element text gets
		 * automatically converted to JSON primitives (number, boolean, null).
		 */
		JsonXMLConfig config = new JsonXMLConfigBuilder()
			.autoArray(true)
			.autoPrimitive(true)
			.prettyPrint(true)
			.build();
		try {
			/*
			 * Create source (XML).
			 */
			XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(input);
			Source source = new StAXSource(reader);
	
			/*
			 * Create result (JSON).
			 */
			XMLStreamWriter writer = new JsonXMLOutputFactory(config).createXMLStreamWriter(output);
			Result result = new StAXResult(writer);
	
			/*
			 * Copy source to result via "identity transform".
			 */
			 TransformerFactory.newInstance().newTransformer().transform(source, result);
		} finally {
			/*
			 * As per StAX specification, XMLStreamReader/Writer.close() doesn't close
			 * the underlying stream.
			 */
			output.close();
			input.close();
		}
	}
}

Copying XML to JSON via StAX Event API

package de.odysseus.staxon.sample.copy;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;

import de.odysseus.staxon.json.JsonXMLConfig;
import de.odysseus.staxon.json.JsonXMLConfigBuilder;
import de.odysseus.staxon.json.JsonXMLOutputFactory;

public class XML2JSON2 {
	/**
	 * Copy/format JSON using {@link XMLEventWriter#add(XMLEventReader)}.
	 * @param args ignored
	 * @throws XMLStreamException
	 * @throws IOException
	 */
	public static void main(String[] args) throws XMLStreamException, IOException {
		InputStream input = XML2JSON2.class.getResourceAsStream("input.xml");
		OutputStream output = System.out;
		/*
		 * If we want to insert JSON array boundaries for multiple elements,
		 * we need to set the <code>autoArray</code> property.
		 * If our XML source was decorated with <code>&lt;?xml-multiple?&gt;</code>
		 * processing instructions, we'd set the <code>multiplePI</code>
		 * property instead.
		 * With the <code>autoPrimitive</code> property set, element text gets
		 * automatically converted to JSON primitives (number, boolean, null).
		 */
		JsonXMLConfig config = new JsonXMLConfigBuilder()
			.autoArray(true)
			.autoPrimitive(true)
			.prettyPrint(true)
			.build();
		try {
			/*
			 * Create reader (XML).
			 */
			XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(input);
	
			/*
			 * Create writer (JSON).
			 */
			XMLEventWriter writer = new JsonXMLOutputFactory(config).createXMLEventWriter(output);
			
			/*
			 * Copy events from reader to writer.
			 */
			writer.add(reader);
			
			/*
			 * Close reader/writer.
			 */
			reader.close();
			writer.close();
		} finally {
			/*
			 * As per StAX specification, XMLEventReader/Writer.close() doesn't close
			 * the underlying stream.
			 */
			output.close();
			input.close();
		}
	}
}
⚠️ **GitHub.com Fallback** ⚠️