Skip to content

Instantly share code, notes, and snippets.

@Stwissel
Last active March 1, 2018 06:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Stwissel/900acc8ed6a46131530ab89bb70b9f9d to your computer and use it in GitHub Desktop.
Save Stwissel/900acc8ed6a46131530ab89bb70b9f9d to your computer and use it in GitHub Desktop.
Json to XML and Back with vert.x
package net.wissel.json2xml;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Stack;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
public class Json2XmlMain {
private class SimpleXMLDoc {
private TransformerHandler hd = null;
private boolean documentStarted = false;
final private ByteArrayOutputStream out = new ByteArrayOutputStream();
private final Stack<String> xmlTagStack = new Stack<String>();
public void addEmptyTag(final String tagName, final Map<String, String> attributes)
throws TransformerConfigurationException, SAXException {
this.openTag(tagName, attributes);
this.closeTag(1);
}
public void closeDocument() throws SAXException {
this.closeTag(-1); // Make sure all tages are closes
// Closing of the document,
this.hd.endDocument();
}
public void closeTag(final int howMany) throws SAXException {
if (howMany < 0) {
while (!this.xmlTagStack.empty()) {
final String closeTag = this.xmlTagStack.pop();
this.hd.endElement("", "", closeTag);
}
} else {
for (int i = 0; i < howMany; i++) {
if (!this.xmlTagStack.empty()) {
final String closeTag = this.xmlTagStack.pop();
this.hd.endElement("", "", closeTag);
} else {
break; // No point looping
}
}
}
}
public void openTag(final String tagName) throws SAXException, TransformerConfigurationException {
this.openTag(tagName, null, null);
}
public void openTag(final String tagName, final Map<String, String> attributes)
throws SAXException, TransformerConfigurationException {
AttributesImpl atts = null;
if (!this.documentStarted) {
this.initializeDoc();
}
// This creates attributes that go inside the element, all
// encoding is
// taken care of
if ((attributes != null) && !attributes.isEmpty()) {
atts = new AttributesImpl();
for (final Entry<String, String> curAtt : attributes.entrySet()) {
atts.addAttribute("", "", curAtt.getKey(), "CDATA", curAtt.getValue());
}
}
// This creates the element with the previously defined
// attributes
this.hd.startElement("", "", tagName, atts);
this.xmlTagStack.push(tagName); // Memorize that we opened it!
}
public void openTag(final String tagName, final String attributeName, final String attributValue)
throws SAXException, TransformerConfigurationException {
final Map<String, String> attributes = new HashMap<>();
if ((attributeName != null) && (attributValue != null)) {
attributes.put(attributeName, attributValue);
}
this.openTag(tagName, attributes);
}
@Override
public String toString() {
return new String(this.out.toByteArray());
}
private void initializeDoc() throws TransformerConfigurationException, SAXException {
final PrintWriter pw = new PrintWriter(this.out); // out comes from
// outside
final StreamResult streamResult = new StreamResult(pw);
// Factory pattern at work
final SAXTransformerFactory tf = (SAXTransformerFactory) TransformerFactory.newInstance();
this.hd = tf.newTransformerHandler();
final Transformer serializer = this.hd.getTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
serializer.setOutputProperty(OutputKeys.METHOD, "xml");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
this.hd.setResult(streamResult);
this.hd.startDocument();
this.documentStarted = true;
}
}
private class Xml2JsonHandler extends DefaultHandler {
final Stack<Object> jStack = new Stack<>();
final JsonObject json = new JsonObject();
public Xml2JsonHandler() {
this.jStack.push(this.json);
}
/**
* @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
* java.lang.String, java.lang.String)
*/
@Override
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
// Get rid of one element
this.jStack.pop();
}
public final JsonObject getJson() {
return this.json;
}
/**
* @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
* java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
@Override
public void startElement(final String uri, final String localName, final String qName,
final Attributes attributes)
throws SAXException {
// We don't process the data cover element
if ("data".equals(qName)) {
return;
}
// Get name and value from the element. Value might be null
final String curName = attributes.getValue("name");
final String curValueCandidate = attributes.getValue("value");
final String curType = attributes.getValue("type");
final Object curValue = this.extractValueWithType(curValueCandidate, curType);
// The current object on the stack
final Object o = this.jStack.peek();
// Play through cases
// Parent is object and element has a value
if ((o instanceof JsonObject) && (curValue != null)) {
((JsonObject) o).put(curName, curValue);
this.jStack.push(o);
} else if ((o instanceof JsonObject) && (curValue == null) && "element".equals(qName)) {
final JsonObject jo = new JsonObject();
((JsonObject) o).put(curName, jo);
this.jStack.push(jo);
} else if ((o instanceof JsonObject) && (curValue == null) && "array".equals(qName)) {
final JsonArray ja = new JsonArray();
((JsonObject) o).put(curName, ja);
this.jStack.push(ja);
} else if ((o instanceof JsonArray) && (curValue != null)) {
((JsonArray) o).add(curValue);
this.jStack.push(o);
} else if ((o instanceof JsonArray) && (curValue == null) && "element".equals(qName)) {
final JsonObject jo = new JsonObject();
((JsonArray) o).add(jo);
this.jStack.push(jo);
} else if ((o instanceof JsonArray) && (curValue == null) && "array".equals(qName)) {
final JsonArray ja = new JsonArray();
((JsonArray) o).add(ja);
this.jStack.push(ja);
}
}
private Object extractValueWithType(String curValueCandidate, String curType) {
Object result = null;
try {
if (curType != null) {
switch (curType) {
case "Boolean":
result = Boolean.valueOf(curValueCandidate);
break;
case "Integer":
result = Integer.valueOf(curValueCandidate);
break;
case "Double":
result = Double.valueOf(curValueCandidate);
break;
case "Long":
result = Long.valueOf(curValueCandidate);
break;
default:
result = curValueCandidate;
break;
}
}
} catch (Throwable t) {
t.printStackTrace();
}
return (result == null) ? curValueCandidate : result;
}
}
public static void main(final String[] args) throws Exception {
if (args.length < 1) {
System.err.println("Usage java net.wissel.json2xml.Main [filename]");
System.exit(1);
}
final String fileName = args[0];
final Json2XmlMain j2x = new Json2XmlMain();
j2x.renderFile(fileName);
}
public void render(final InputStream in, final PrintStream out)
throws IOException, SAXException, TransformerConfigurationException, ParserConfigurationException {
// Get the JsonObject
final Scanner scanner = new Scanner(in);
final String source = scanner.useDelimiter("\\Z").next();
scanner.close();
in.close();
final Buffer buffer = Buffer.buffer(source);
final JsonObject jo = new JsonObject(buffer);
jo.put("today", new Date().toString());
// jo = this.createSample();
out.println(jo.encodePrettily());
out.println("-------------------------------------------------------------");
final String xmlResult = this.json2xmlString(jo);
out.println(xmlResult);
out.println("-------------------------------------------------------------");
final JsonObject jsonResult = this.xmlString2Json(xmlResult);
out.println(jsonResult.encodePrettily());
}
private void extractValue(final String key, final Object value, final SimpleXMLDoc sd) throws Exception {
if (value instanceof JsonObject) {
final JsonObject nextJson = (JsonObject) value;
sd.openTag("element", "name", key);
this.parseToOutput(nextJson, sd);
sd.closeTag(1);
} else if (value instanceof JsonArray) {
final JsonArray oneArray = (JsonArray) value;
sd.openTag("array", "name", key);
oneArray.forEach(arrayElement -> {
try {
this.extractValue(key, arrayElement, sd);
} catch (final Exception e) {
e.printStackTrace();
}
});
sd.closeTag(1);
} else {
final Map<String, String> attributes = this.getAttributeMap(key, value);
sd.addEmptyTag("element", attributes);
}
}
private Map<String, String> getAttributeMap(String key, Object value) {
final Map<String, String> result = new HashMap<>();
result.put("name", key);
result.put("value", String.valueOf(value));
result.put("type", value.getClass().getSimpleName());
return result;
}
private String json2xmlString(final JsonObject jo) throws SAXException, TransformerConfigurationException {
final SimpleXMLDoc sd = new SimpleXMLDoc();
sd.openTag("data");
this.parseToOutput(jo, sd);
sd.closeDocument();
return sd.toString();
}
private void parseToOutput(final JsonObject json, final SimpleXMLDoc sd) {
json.forEach(entry -> {
final String key = entry.getKey();
final Object value = entry.getValue();
try {
this.extractValue(key, value, sd);
} catch (final Exception e) {
e.printStackTrace();
}
});
}
private void renderFile(final String fileName) throws Exception {
final File file = new File(fileName);
if (!file.exists() || file.isDirectory()) {
System.err.println("File does not exist:" + fileName);
return;
}
final FileInputStream in = new FileInputStream(file);
this.render(in, System.out);
}
private JsonObject xmlString2Json(final String xmlResult)
throws SAXException, IOException, ParserConfigurationException {
final SAXParserFactory factory = SAXParserFactory.newInstance();
final SAXParser saxParser = factory.newSAXParser();
final Xml2JsonHandler dh = new Xml2JsonHandler();
saxParser.parse(new ByteArrayInputStream(xmlResult.getBytes()), dh);
return dh.getJson();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment