blob: 6243c0df4512d952ebc1daf9dfd736c3bff8ccc0 [file] [log] [blame]
/*******************************************************************************
* 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.ofbiz.base.json;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import org.ofbiz.base.lang.SourceMonitored;
import org.ofbiz.base.util.IndentingWriter;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilIO;
@SourceMonitored
public class JSONWriter {
private final IndentingWriter writer;
private final FallbackHandler fallbackHandler;
public JSONWriter(IndentingWriter writer) {
this(writer, StandardFallbackHandler);
}
public JSONWriter(IndentingWriter writer, FallbackHandler fallbackHandler) {
this.writer = writer;
this.fallbackHandler = fallbackHandler;
}
public JSONWriter(Writer writer) {
this(IndentingWriter.makeIndentingWriter(writer));
}
public JSONWriter(Writer writer, FallbackHandler fallbackHandler) {
this(IndentingWriter.makeIndentingWriter(writer), fallbackHandler);
}
public IndentingWriter getWriter() {
return writer;
}
public JSONWriter close() throws IOException {
getWriter().close();
return this;
}
public JSONWriter write(byte b) throws IOException {
writer.write(Byte.toString(b));
return this;
}
public JSONWriter write(short s) throws IOException {
writer.write(Short.toString(s));
return this;
}
public JSONWriter write(int i) throws IOException {
writer.write(Integer.toString(i));
return this;
}
public JSONWriter write(long l) throws IOException {
writer.write(Long.toString(l));
return this;
}
public JSONWriter write(float f) throws IOException {
writer.write(Float.toString(f));
return this;
}
public JSONWriter write(double d) throws IOException {
writer.write(Double.toString(d));
return this;
}
public JSONWriter write(char c) throws IOException {
write(Character.toString(c));
return this;
}
public JSONWriter write(String s) throws IOException {
writer.write('"');
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '\\': writer.write("\\\\"); continue;
case '/': writer.write("\\/"); continue;
case '"': writer.write("\\\""); continue;
case '\b': writer.write("\\b"); continue;
case '\f': writer.write("\\f"); continue;
case '\n': writer.write("\\n"); continue;
case '\r': writer.write("\\r"); continue;
case '\t': writer.write("\\t"); continue;
}
if (c >= 32 && c < 256) {
writer.write(c);
} else {
writer.write("\\u");
String n = Integer.toString(c, 16);
for (int j = 4 - n.length(); j > 0; j--) writer.write('0');
writer.write(n);
}
}
writer.write('"');
return this;
}
public <K, V> JSONWriter write(Map<K, V> m) throws IOException {
writer.write('{');
writer.push();
Iterator<Map.Entry<K, V>> it = m.entrySet().iterator();
if (it.hasNext()) writer.newline();
while (it.hasNext()) {
Map.Entry<K, V> entry = it.next();
write(entry.getKey());
writer.write(':');
writer.space();
write(entry.getValue());
if (it.hasNext()) writer.write(',');
writer.newline();
}
writer.pop();
writer.write('}');
return this;
}
public <E> JSONWriter write(Collection<E> c) throws IOException {
this.write(c.iterator());
return this;
}
public <E> JSONWriter write(Iterator<E> it) throws IOException {
writer.write('[');
writer.push();
if (it.hasNext()) writer.newline();
while (it.hasNext()) {
write(it.next());
if (it.hasNext()) writer.write(',');
writer.newline();
}
writer.pop();
writer.write(']');
return this;
}
public <T> JSONWriter write(T... o) throws IOException {
writer.write('[');
writer.push();
for (int i = 0; i < o.length; i++) {
if (i != 0) writer.write(',');
writer.newline();
write(o[i]);
}
if (o.length > 0) writer.newline();
writer.pop();
writer.write(']');
return this;
}
public JSONWriter write(Object o) throws IOException {
if (o == null) {
writer.write("null");
return this;
} else if (o instanceof Boolean) {
writer.write(((Boolean) o).booleanValue() ? "true" : "false");
return this;
} else if (o instanceof String) {
return write((String) o);
} else if (o instanceof Map<?, ?>) {
return write(UtilGenerics.<Map<?, ?>>cast(o));
} else if (o instanceof Collection<?>) {
return write(UtilGenerics.<Collection<?>>cast(o));
} else if (o instanceof Iterator<?>) {
return write(UtilGenerics.<Iterator<?>>cast(o));
} else if (o instanceof Byte) {
return write(((Byte) o).byteValue());
} else if (o instanceof Character) {
return write(((Character) o).charValue());
} else if (o instanceof Double) {
return write(((Double) o).doubleValue());
} else if (o instanceof Float) {
return write(((Float) o).floatValue());
} else if (o instanceof Integer) {
return write(((Integer) o).intValue());
} else if (o instanceof Long) {
return write(((Long) o).longValue());
} else if (o instanceof Short) {
return write(((Short) o).shortValue());
} else if (o.getClass().isArray()) {
return write((Object[]) o);
} else {
fallbackHandler.writeJSON(this, writer, o);
return this;
}
}
public interface FallbackHandler {
void writeJSON(JSONWriter json, Writer writer, Object o) throws IOException;
}
public static final FallbackHandler StandardFallbackHandler = new FallbackHandler() {
public void writeJSON(JSONWriter json, Writer writer, Object o) throws IOException {
throw new IOException("Can't write(" + o + ":" + o.getClass() + ")");
}
};
public static final FallbackHandler ResolvingFallbackHandler = new FallbackHandler() {
public void writeJSON(JSONWriter json, Writer writer, Object o) throws IOException {
StringBuilder sb = new StringBuilder();
UtilIO.writeObject(sb, o);
writer.write("resolve(");
json.write(sb.toString());
writer.write(")");
}
};
}