/** * $Id: $ * $Date: $ * */ package org.xmlsh.json; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.List; import javax.xml.crypto.dsig.TransformException; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import javax.xml.stream.events.Attribute; import javax.xml.stream.events.EndElement; import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; import net.sf.saxon.s9api.SaxonApiException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.xmlsh.core.CoreException; import org.xmlsh.core.XValue; import org.xmlsh.sh.shell.SerializeOpts; import org.xmlsh.util.Util; import com.fasterxml.jackson.core.JsonToken; public class JSONXConverter extends JXConverter { static final String kJXML_URI = "http://www.ibm.com/xmlns/prod/2009/jsonx"; static final QName kATTR_NAME = new QName("name"); static final QName kELEM_OBJECT = new QName(kJXML_URI, "object"); // A JSON Object static final QName kELEM_STRING = new QName(kJXML_URI, "string"); // A JSON STRING static final QName kELEM_NUMBER = new QName(kJXML_URI, "number"); // A JSON NUMBER static final QName kELEM_ARRAY = new QName(kJXML_URI, "array"); // A JSON ARRAY static final QName kELEM_BOOLEAN = new QName(kJXML_URI, "boolean"); // A JSON Literal (true,false) static final QName kELEM_NULL = new QName(kJXML_URI, "null"); // A JSON Literal null public static Logger mLogger = LogManager.getLogger(); class JConverter extends JSONConverter { protected JConverter(XMLStreamReader reader, OutputStream os) throws ConverterException { super(reader, os); } @Override public boolean startElement(StartElement start, QName name) throws ConverterException { try { if(name.equals(kELEM_OBJECT)) writeObject(start); else if(name.equals(kELEM_ARRAY)) writeArray(start); else if(name.equals(kELEM_NUMBER)) writeNumber(start); else if(name.equals(kELEM_BOOLEAN)) writeBoolean(start); else if(name.equals(kELEM_NULL)) writeNull(start); else if(name.equals(kELEM_STRING)) writeString(start); else throw new ConverterException("Depreciated element not supported: " + start.toString()); } catch (ConverterException e) { throw e; } catch (Exception e) { Util.wrapException(e, ConverterException.class); } return true; } private void writeString(StartElement start) throws XMLStreamException, UnsupportedEncodingException, FileNotFoundException, IOException, TransformException, SaxonApiException, CoreException { writeNameField( start ); String chars = readString(); mGenerator.writeString(chars); } private void writeNameField(StartElement start) throws IOException { String name = getAttr( start , kATTR_NAME ); if( ! Util.isBlank(name)) mGenerator.writeFieldName(name); } private String getAttr(StartElement start, QName attr) { Attribute a = start.getAttributeByName(attr); if(a == null) return null; return a.getValue(); } private void writeNull(StartElement start) throws IOException, ConverterException, XMLStreamException { writeNameField( start ); mGenerator.writeNull(); } private void writeBoolean(StartElement start) throws XMLStreamException, IOException, ConverterException { writeNameField( start ); String chars = readString(); chars = chars.trim(); mGenerator.writeBoolean(Util.parseBoolean(chars)); } private void writeNumber(StartElement start) throws ConverterException, IOException, XMLStreamException { writeNameField( start ); String chars = readString(); chars = chars.trim(); mGenerator.writeNumber(chars); } private void writeArray(StartElement start) throws IOException, ConverterException { writeNameField(start); mGenerator.writeStartArray(); do { if(!parse()) break; } while (true); mGenerator.writeEndArray(); } private void writeObject(StartElement start) throws IOException, ConverterException { writeNameField(start); mGenerator.writeStartObject(); do { if(!parse()) break; } while (true); mGenerator.writeEndObject(); } @Override protected boolean startDocument(XMLEvent e) throws ConverterException { return true; } @Override protected boolean endElement(EndElement asEndElement) throws ConverterException { return false; } @Override protected boolean endDocument(XMLEvent e) throws ConverterException { return false; } @Override protected boolean characters(XMLEvent e) { // Ignore unexpected chars return true; } } class XConverter extends XMLConverter { private String mFieldName; protected XConverter(InputStream is, XMLStreamWriter sw) throws ConverterException { super(is, sw); } // Write a value and @Override void writeArray() throws ConverterException { try { JsonToken tok; writeStartElement( kELEM_ARRAY ); writeFieldAttr(); while ((tok = nextToken()) != null && tok != JsonToken.END_ARRAY) { writeValue(tok); } writeEndElement(); } catch (XMLStreamException e) { throw new ConverterException(e); } } @Override void writeObject() throws ConverterException { JsonToken tok; try { writeStartElement( kELEM_OBJECT ); writeFieldAttr(); while ((tok = nextToken()) == JsonToken.FIELD_NAME ) writeMember(); if(tok == null) throw new ConverterException("Unexpected EOF"); if(tok != JsonToken.END_OBJECT) throw new ConverterException("Unexpected token: " + tok); writeEndElement(); } catch (XMLStreamException e) { throw new ConverterException(e); } } private void writeMember() throws ConverterException { try { mFieldName = mParser.getCurrentName(); writeValue(nextToken()); } catch (IOException e) { throw new ConverterException(e); } } @Override void writeBoolean(boolean value) throws ConverterException { try { writeStartElement( kELEM_BOOLEAN ); writeFieldAttr(); writeCharacters(value ? "true" : "false"); writeEndElement(); } catch (XMLStreamException e) { throw new ConverterException(e); } } private void writeFieldAttr() throws XMLStreamException { if( mFieldName != null ) { writeAttribute(kATTR_NAME, mFieldName); mFieldName = null ; } } @Override void writeNull() throws ConverterException { try { writeStartElement(kELEM_NULL); writeFieldAttr(); writeEndElement(); } catch (XMLStreamException e) { throw new ConverterException(e); } } @Override void writeNumber() throws ConverterException { try { writeStartElement(kELEM_NUMBER); writeFieldAttr(); writeCharacters( getStringValue() ); writeEndElement(); } catch (XMLStreamException e) { throw new ConverterException(e); } } @Override void writeString(String s) throws ConverterException { try { writeStartElement(kELEM_STRING); writeFieldAttr(); writeCharacters(s); writeEndElement(); } catch (XMLStreamException e) { throw new ConverterException(e); } } } public JSONXConverter(SerializeOpts serializeOpts, List<XValue> mArgs) { super( serializeOpts, mArgs); } @Override JSONConverter newJConverter(XMLStreamReader reader, OutputStream os) throws ConverterException { return new JConverter(reader, os); } @Override XMLConverter newXMLConverter(InputStream is, XMLStreamWriter sw) throws ConverterException { return new XConverter(is, sw); } } /* * Copyright (C) 2008-2012 David A. Lee. * * The contents of this file are subject to the "Simplified BSD License" (the * "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/bsd-license.php * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific language governing rights and limitations under the License. * * The Original Code is: all this file. * * The Initial Developer of the Original Code is David A. Lee * * Portions created by (your name) are Copyright (C) (your legal entity). All * Rights Reserved. * * Contributor(s): David A. Lee */