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...
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><?xml-multiple?></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();
}
}
}
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><?xml-multiple?></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();
}
}
}