com.ibm.commons.util.io.json.JsonGenerator Maven / Gradle / Ivy
The newest version!
/*
* © Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.ibm.commons.util.io.json;
import java.io.IOException;
import java.io.Writer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import com.ibm.commons.util.StringUtil;
/**
* JSON text generator.
*
* This class provides some methods for generating JSON object representation. It uses
* a factory to deal with the actual object classes.
*
* @ibm-api
*/
public class JsonGenerator {
/**
* Convert an object hierarchy to a JSON text.
* The string is written in a compact form (no extra spaces/new lines inserted).
* @param factory the object factory
* @param value the convert to serialize
* @return the resulting JSON string
* @throws IOException
* @throws JsonException
* @ibm-api
*/
public static String toJson(JsonFactory factory, Object value) throws IOException, JsonException {
return toJson(factory,value,true);
}
/**
* Convert an object hierarchy to a JSON text.
* @param factory the object factory
* @param value the convert to serialize
* @param compact indicates if the string should be in a compact format
* @return the resulting JSON string
* @throws IOException
* @throws JsonException
* @ibm-api
*/
public static String toJson(JsonFactory factory, Object value, boolean compact) throws IOException, JsonException {
StringGenerator gen = new StringGenerator(factory,compact);
gen.toJson(value);
return gen.b.toString();
}
/**
* Convert an object hierarchy to a JSON text and append it to an existing String builder.
* @param factory the object factory
* @param b the StringBuilder to append the text to
* @param value the convert to serialize
* @param compact indicates if the string should be in a compact format
* @return the resulting JSON string
* @throws IOException
* @throws JsonException
* @ibm-api
*/
public static StringBuilder toJson(JsonFactory factory, StringBuilder b, Object value, boolean compact) throws IOException, JsonException {
StringBuilderGenerator gen = new StringBuilderGenerator(factory,b,compact);
gen.toJson(value);
return b;
}
/**
* Convert an object hierarchy to a JSON text in a writer.
* @param factory the object factory
* @param writer the writer to write to
* @param value the convert to serialize
* @param compact indicates if the string should be in a compact format
* @throws IOException
* @throws JsonException
* @ibm-api
*/
public static void toJson(JsonFactory factory, Writer writer, Object value, boolean compact) throws IOException, JsonException {
WriterGenerator gen = new WriterGenerator(factory,writer,compact);
gen.toJson(value);
}
/**
* Generator base class.
* @ibm-not-published
*/
public abstract static class Generator {
private JsonFactory factory;
private boolean compact;
private int indentLevel;
protected Generator(JsonFactory factory, boolean compact) {
this.factory = factory;
this.compact = compact;
}
public abstract void out(char c) throws IOException;
public abstract void out(String s) throws IOException;
public JsonFactory getFactory() {
return factory;
}
public int getIndentLevel() {
return indentLevel;
}
public void setIndentLevel(int indentLevel) {
this.indentLevel = indentLevel;
}
public void incIndent() {
indentLevel++;
}
public void decIndent() {
indentLevel--;
}
public boolean isCompact() {
return compact;
}
public void toJson(Object value) throws IOException, JsonException {
outLiteral(value);
}
public void outLiteral(Object value) throws IOException, JsonException {
outLiteral(value, false);
}
/**
* Writes a property value.
*
* @param value The value to write.
* @param named true
if the property is named.
* @throws IOException
* @throws JsonException
*/
protected void outLiteral(Object value, boolean named) throws IOException, JsonException {
if(factory.isNull(value)) {
outNull(); // $NON-NLS-1$
} else if(factory.isString(value)) {
outStringLiteral(factory.getString(value));
} else if(factory.isNumber(value)) {
outNumberLiteral(factory.getNumber(value));
} else if(factory.isBoolean(value)) {
outBooleanLiteral(factory.getBoolean(value));
} else if(factory.isObject(value)) {
outObject(value, named);
} else if(factory.isArray(value)) {
outArrayLiteral(value, named);
} else if(value instanceof JsonReference) {
outReference((JsonReference)value);
} else {
throw new JsonException(null,"Unknown literal of class {0}", value!=null?value.getClass().getName():""); // $NLS-JsonGenerator.Unknownliteralofclass0-1$ $NON-NLS-2$
}
}
public void outNull() throws IOException, JsonException {
out("null"); // $NON-NLS-1$
}
public void outObject(Object object) throws IOException, JsonException {
outObject(object, false);
}
/**
* Writes a JSON object property.
*
* @param object The object to write.
* @param named true
if the object is named.
* @throws IOException
* @throws JsonException
*/
protected void outObject(Object object, boolean named) throws IOException, JsonException {
if ( named ) {
// Named objects are not indented
out(' ');
} else {
indent();
}
startObject(object);
boolean coma = false;
for(Iterator it = factory.iterateObjectProperties(object); it.hasNext(); ) {
String propName = it.next();
Object propValue = factory.getProperty(object, propName);
if(coma) {
out(',');
} else {
coma = true;
}
indentLevel++;
nl();
indent();
outPropertyName(propName);
out(':');
outLiteral(propValue, true);
indentLevel--;
}
nl();
indent();
endObject(object);
}
protected void startObject(Object object) throws IOException, JsonException {
out('{');
}
protected void endObject(Object object) throws IOException, JsonException {
out('}');
}
public void outPropertyName(String s) throws IOException {
outStringLiteral(s);
}
public void outStringLiteral(String s) throws IOException {
out('\"');
int len = s.length();
for(int i=0; i=32 && c<=128) {
out(c);
} else {
out("\\u"); //$NON-NLS-1$
out(StringUtil.toUnsignedHex(c,4));
}
}
}
}
out('\"');
}
public void outCharInString(char c) throws IOException {
switch(c) {
case '"': {
out("\\\""); //$NON-NLS-1$
} break;
case '\'': {
out("\\\'"); //$NON-NLS-1$
} break;
case '\\': {
out("\\\\"); //$NON-NLS-1$
} break;
case '/': {
out("\\/"); //$NON-NLS-1$
} break;
case '\b': {
out("\\b"); //$NON-NLS-1$
} break;
case '\f': {
out("\\f"); //$NON-NLS-1$
} break;
case '\n': {
out("\\n"); //$NON-NLS-1$
} break;
case '\r': {
out("\\r"); //$NON-NLS-1$
} break;
case '\t': {
out("\\t"); //$NON-NLS-1$
} break;
default: {
// Ensure that it will be transmitted correctly...
if(c>=32 && c<=128) {
out(c);
} else {
out("\\u"); //$NON-NLS-1$
out(StringUtil.toUnsignedHex(c,4));
}
}
}
}
public void outNumberLiteral(double d) throws IOException {
long l = (long)d;
if(((double)l)==d) {
String s = Long.toString(l);
out(s);
} else {
String s = Double.toString(d);
out(s);
}
}
public void outDateLiteral_(Date value) throws IOException {
String s = dateToString(value);
outStringLiteral(s);
}
public void outIntLiteral(int d) throws IOException {
String s = Integer.toString(d);
out(s);
}
public void outLongLiteral(long d) throws IOException {
String s = Long.toString(d);
out(s);
}
public void outBooleanLiteral(boolean b) throws IOException {
out(b?"true":"false"); //$NON-NLS-1$ //$NON-NLS-2$
}
public void outArrayLiteral(Object array) throws IOException, JsonException {
outArrayLiteral(array, false);
}
/**
* Writes an array property.
*
* @param array The array to write.
* @param named true
if the property is named.
* @throws IOException
* @throws JsonException
*/
protected void outArrayLiteral(Object array, boolean named) throws IOException, JsonException {
if ( named ) {
// Named arrays are not indented
out(' ');
} else {
indent();
}
out('[');
nl();
boolean coma = false;
for(Iterator