org.apache.wink.json4j.internal.Serializer Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.wink.json4j.internal;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.wink.json4j.JSONArray;
import org.apache.wink.json4j.JSONObject;
import org.apache.wink.json4j.JSONString;
import org.apache.wink.json4j.OrderedJSONObject;
/**
* Class to handle serialization of a JSON object to a JSON string.
*/
public class Serializer {
/**
* The writer to use when writing this JSON object.
*/
private Writer writer;
/**
* Create a serializer on the specified output stream writer.
*/
public Serializer(Writer writer) {
super();
this.writer = writer;
}
/**
* Method to flush the current writer.
* @throws IOException Thrown if an error occurs during writer flush.
*/
public void flush() throws IOException {
writer.flush();
}
/**
* Method to close the current writer.
* @throws IOException Thrown if an error occurs during writer close.
*/
public void close() throws IOException {
writer.close();
}
/**
* Method to write a raw string to the writer.
* @param s The String to write.
* @throws IOException Thrown if an error occurs during write.
*/
public Serializer writeRawString(String s) throws IOException {
writer.write(s);
return this;
}
/**
* Method to write the text string 'null' to the output stream (null JSON object).
* @throws IOException Thrown if an error occurs during write.
*/
public Serializer writeNull() throws IOException {
writeRawString("null");
return this;
}
/**
* Method to write a number to the current writer.
* @param value The number to write to the JSON output string.
* @throws IOException Thrown if an error occurs during write.
*/
public Serializer writeNumber(Number value) throws IOException {
if (null == value) return writeNull();
if (value instanceof Float) {
if (((Float)value).isNaN()) return writeNull();
if (Float.NEGATIVE_INFINITY == value.floatValue()) return writeNull();
if (Float.POSITIVE_INFINITY == value.floatValue()) return writeNull();
}
if (value instanceof Double) {
if (((Double)value).isNaN()) return writeNull();
if (Double.NEGATIVE_INFINITY == value.doubleValue()) return writeNull();
if (Double.POSITIVE_INFINITY == value.doubleValue()) return writeNull();
}
writeRawString(value.toString());
return this;
}
/**
* Method to write a boolean value to the output stream.
* @param value The Boolean object to write out as a JSON boolean.
* @throws IOException Thrown if an error occurs during write.
*/
public Serializer writeBoolean(Boolean value) throws IOException {
if (null == value) return writeNull();
writeRawString(value.toString());
return this;
}
/**
* Method to generate a string with a particular width. Alignment is done using zeroes if it does not meet the width requirements.
* @param s The string to write
* @param len The minimum length it should be, and to align with zeroes if length is smaller.
* @return A string properly aligned/correct width.
*/
private String rightAlignedZero(String s, int len) {
if (len == s.length()) return s;
StringBuffer sb = new StringBuffer(s);
while (sb.length() < len) {
sb.insert(0, '0');
}
return sb.toString();
}
/**
* Method to write a String out to the writer, encoding special characters and unicode characters properly.
* @param value The string to write out.
* @throws IOException Thrown if an error occurs during write.
*/
public Serializer writeString(String value) throws IOException {
if (null == value) return writeNull();
writer.write('"');
char[] chars = value.toCharArray();
for (int i=0; i= 32) && (c <= 126)) {
writer.write(c);
} else {
writer.write("\\u");
writer.write(rightAlignedZero(Integer.toHexString(c),4));
}
}
}
writer.write('"');
return this;
}
/**
* Method to write out a generic JSON type.
* @param object The JSON compatible object to serialize.
* @throws IOException Thrown if an error occurs during write, or if a nonJSON compatible Java object is passed..
*/
private Serializer write(Object object) throws IOException {
if (null == object) return writeNull();
// Serialize the various types!
Class clazz = object.getClass();
if (Number.class.isAssignableFrom(clazz)) return writeNumber((Number) object);
if (Boolean.class.isAssignableFrom(clazz)) return writeBoolean((Boolean) object);
if (JSONObject.class.isAssignableFrom(clazz)) return writeObject((JSONObject) object);
if (JSONArray.class.isAssignableFrom(clazz)) return writeArray((JSONArray) object);
if (JSONString.class.isAssignableFrom(clazz)) return writeRawString(((JSONString) object).toJSONString());
if (String.class.isAssignableFrom(clazz)) return writeString((String) object);
throw new IOException("Attempting to serialize unserializable object: '" + object + "'");
}
/**
* Method to write a complete JSON object to the stream.
* @param object The JSON object to write out.
* @throws IOException Thrown if an error occurs during write.
*/
public Serializer writeObject(JSONObject object) throws IOException {
if (null == object) return writeNull();
// write header
writeRawString("{");
indentPush();
Iterator iter = null;
if (object instanceof OrderedJSONObject) {
iter = ((OrderedJSONObject)object).getOrder();
} else {
List propertyNames = getPropertyNames(object);
iter = propertyNames.iterator();
}
while ( iter.hasNext() ) {
Object key = iter.next();
if (!(key instanceof String)) throw new IOException("attempting to serialize object with an invalid property name: '" + key + "'" );
Object value = object.get(key);
if (!JSONObject.isValidObject(value)) throw new IOException("attempting to serialize object with an invalid property value: '" + value + "'");
newLine();
indent();
writeString((String)key);
writeRawString(":");
space();
write(value);
if (iter.hasNext()) writeRawString(",");
}
// write trailer
indentPop();
newLine();
indent();
writeRawString("}");
return this;
}
/**
* Method to write a JSON array out to the stream.
* @param value The JSON array to write out.
* @throws IOException Thrown if an error occurs during write.
*/
public Serializer writeArray(JSONArray value) throws IOException {
if (null == value) return writeNull();
// write header
writeRawString("[");
indentPush();
for (Iterator iter=value.iterator(); iter.hasNext(); ) {
Object element = iter.next();
if (!JSONObject.isValidObject(element)) throw new IOException("attempting to serialize array with an invalid element: '" + value + "'");
newLine();
indent();
write(element);
if (iter.hasNext()) writeRawString(",");
}
// write trailer
indentPop();
newLine();
indent();
writeRawString("]");
return this;
}
//---------------------------------------------------------------
// pretty printing overridables
//---------------------------------------------------------------
/**
* Method to write a space to the output writer.
* @throws IOException Thrown if an error occurs during write.
*/
public void space() throws IOException {
}
/**
* Method to write a newline to the output writer.
* @throws IOException Thrown if an error occurs during write.
*/
public void newLine() throws IOException {
}
/**
* Method to write an indent to the output writer.
* @throws IOException Thrown if an error occurs during write.
*/
public void indent() throws IOException {
}
/**
* Method to increase the indent depth of the output writer.
* @throws IOException Thrown if an error occurs during write.
*/
public void indentPush() {
}
/**
* Method to reduce the indent depth of the output writer.
*/
public void indentPop() {
}
/**
* Method to get a list of all the property names stored in a map.
*/
public List getPropertyNames(Map map) {
return new ArrayList(map.keySet());
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy