Converting JSON to XML

Christoph Beck edited this page Dec 18, 2011 · 5 revisions

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 JSON to XML using either of those techniques.

Consider the following JSON sample:

input.json

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

With StAXON's Mapping Convention, fields prefixed with "@" are interpreted as attributes and the "$" field represents text content.

Therefore, converting the above to XML yields

output.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>

Here's the code...

Copying JSON to XML via XSL Transformation

package de.odysseus.staxon.sample.copy;

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

import javax.xml.stream.XMLOutputFactory;
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.JsonXMLInputFactory;
import de.odysseus.staxon.xml.util.PrettyXMLStreamWriter;

public class JSON2XML1 {
	/**
	 * Copy/format JSON as XML using {@link Transformer#transform(Source, Result)}.
	 * @param args ignored
	 * @throws TransformerException
	 * @throws XMLStreamException
	 */
	public static void main(String[] args) throws Exception {
		InputStream input = JSON2XML1.class.getResourceAsStream("input.json");
		OutputStream output = System.out;
		/*
		 * If the <code>multiplePI</code> property is
		 * set to <code>true</code>, the StAXON reader will generate
		 * <code>&lt;xml-multiple&gt;</code> processing instructions
		 * which would be copied to the XML output.
		 * These can be used by StAXON when converting back to JSON
		 * to trigger array starts.
		 * Set to <code>false</code> if you don't need to go back to JSON.
		 */
		JsonXMLConfig config = new JsonXMLConfigBuilder().multiplePI(false).build();
		try {
			/*
			 * Create source (JSON).
			 */
			XMLStreamReader reader = new JsonXMLInputFactory(config).createXMLStreamReader(input);
			Source source = new StAXSource(reader);
			
			/*
			 * Create result (XML).
			 */
			XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(output);
			Result result = new StAXResult(new PrettyXMLStreamWriter(writer)); // format output
			
			/*
			 * 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 JSON to XML via StAX Event API

package de.odysseus.staxon.sample.copy;

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

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

import de.odysseus.staxon.json.JsonXMLConfig;
import de.odysseus.staxon.json.JsonXMLConfigBuilder;
import de.odysseus.staxon.json.JsonXMLInputFactory;
import de.odysseus.staxon.xml.util.PrettyXMLEventWriter;

public class JSON2XML2 {
	/**
	 * Copy/format JSON as XML using {@link XMLEventWriter#add(XMLEventReader)}.
	 * @param args ignored
	 * @throws XMLStreamException
	 */
	public static void main(String[] args) throws Exception {
		InputStream input = JSON2XML2.class.getResourceAsStream("input.json");
		OutputStream output = System.out;
		/*
		 * If the <code>multiplePI</code> property is
		 * set to <code>true</code>, the StAXON reader will generate
		 * <code>&lt;xml-multiple&gt;</code> processing instructions
		 * which would be copied to the XML output.
		 * These can be used by StAXON when converting back to JSON
		 * to trigger array starts.
		 * Set to <code>false</code> if you don't need to go back to JSON.
		 */
		JsonXMLConfig config = new JsonXMLConfigBuilder().multiplePI(false).build();
		try {
			/*
			 * Create reader (JSON).
			 */
			XMLEventReader reader = new JsonXMLInputFactory(config).createXMLEventReader(input);
			
			/*
			 * Create writer (XML).
			 */
			XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(output);
			writer = new PrettyXMLEventWriter(writer); // format 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();
		}
	}
}