Fixed issue 52 by switching Gson.toJson methods to use Appendable instead of java.io.Writer

This commit is contained in:
Inderjeet Singh 2008-11-26 19:13:14 +00:00
parent 59be02d4de
commit 9bcbb4cfdc
8 changed files with 134 additions and 106 deletions

View File

@ -16,6 +16,8 @@
package com.google.gson;
import java.io.IOException;
/**
* A simple implementation of the {@link JsonElementVisitor} that simply delegates the method
* invocation onto a {@code delegate} instance of the {@link JsonElementVisitor}. This object
@ -50,62 +52,66 @@ class DelegatingJsonElementVisitor implements JsonElementVisitor {
this.delegate = delegate;
}
public void endArray(JsonArray array) {
public void endArray(JsonArray array) throws IOException {
delegate.endArray(array);
}
public void endObject(JsonObject object) {
public void endObject(JsonObject object) throws IOException {
delegate.endObject(object);
}
public void startArray(JsonArray array) {
public void startArray(JsonArray array) throws IOException {
delegate.startArray(array);
}
public void startObject(JsonObject object) {
public void startObject(JsonObject object) throws IOException {
delegate.startObject(object);
}
public void visitArrayMember(JsonArray parent, JsonPrimitive member, boolean isFirst) {
public void visitArrayMember(JsonArray parent, JsonPrimitive member,
boolean isFirst) throws IOException {
delegate.visitArrayMember(parent, member, isFirst);
}
public void visitArrayMember(JsonArray parent, JsonArray member, boolean isFirst) {
public void visitArrayMember(JsonArray parent, JsonArray member,
boolean isFirst) throws IOException {
delegate.visitArrayMember(parent, member, isFirst);
}
public void visitArrayMember(JsonArray parent, JsonObject member, boolean isFirst) {
public void visitArrayMember(JsonArray parent, JsonObject member,
boolean isFirst) throws IOException {
delegate.visitArrayMember(parent, member, isFirst);
}
public void visitObjectMember(
JsonObject parent, String memberName, JsonPrimitive member, boolean isFirst) {
public void visitObjectMember(JsonObject parent, String memberName, JsonPrimitive member,
boolean isFirst) throws IOException {
delegate.visitObjectMember(parent, memberName, member, isFirst);
}
public void visitObjectMember(
JsonObject parent, String memberName, JsonArray member, boolean isFirst) {
public void visitObjectMember(JsonObject parent, String memberName, JsonArray member,
boolean isFirst) throws IOException {
delegate.visitObjectMember(parent, memberName, member, isFirst);
}
public void visitObjectMember(
JsonObject parent, String memberName, JsonObject member, boolean isFirst) {
public void visitObjectMember(JsonObject parent, String memberName, JsonObject member,
boolean isFirst) throws IOException {
delegate.visitObjectMember(parent, memberName, member, isFirst);
}
public void visitNullObjectMember(JsonObject parent, String memberName, boolean isFirst) {
public void visitNullObjectMember(JsonObject parent, String memberName,
boolean isFirst) throws IOException {
delegate.visitNullObjectMember(parent, memberName, isFirst);
}
public void visitPrimitive(JsonPrimitive primitive) {
public void visitPrimitive(JsonPrimitive primitive) throws IOException {
delegate.visitPrimitive(primitive);
}
public void visitNull() {
public void visitNull() throws IOException {
delegate.visitNull();
}
public void visitNullArrayMember(JsonArray parent, boolean isFirst) {
public void visitNullArrayMember(JsonArray parent, boolean isFirst) throws IOException {
delegate.visitNullArrayMember(parent, isFirst);
}
}

View File

@ -17,7 +17,6 @@
package com.google.gson;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
@ -191,7 +190,7 @@ public final class Gson {
* of Java. Note that this method works fine if the any of the object fields are of generic type,
* just the object itself should not be of a generic type. If the object is of generic type, use
* {@link #toJson(Object, Type)} instead. If you want to write out the object to a
* {@link Writer}, use {@link #toJson(Object, Writer)} instead.
* {@link Writer}, use {@link #toJson(Object, Appendable)} instead.
*
* @param src the object for which Json representation is to be created setting for Gson
* @return Json representation of {@code src}.
@ -207,7 +206,7 @@ public final class Gson {
* This method serializes the specified object, including those of generic types, into its
* equivalent Json representation. This method must be used if the specified object is a generic
* type. For non-generic objects, use {@link #toJson(Object)} instead. If you want to write out
* the object to a {@link Writer}, use {@link #toJson(Object, Type, Writer)} instead.
* the object to a {@link Appendable}, use {@link #toJson(Object, Type, Appendable)} instead.
*
* @param src the object for which JSON representation is to be created
* @param typeOfSrc The specific genericized type of src. You can obtain
@ -231,24 +230,28 @@ public final class Gson {
* {@code getClass()} loses the generic type information because of the Type Erasure feature
* of Java. Note that this method works fine if the any of the object fields are of generic type,
* just the object itself should not be of a generic type. If the object is of generic type, use
* {@link #toJson(Object, Type, Writer)} instead.
* {@link #toJson(Object, Type, Appendable)} instead.
*
* @param src the object for which Json representation is to be created setting for Gson
* @param writer Writer to which the Json representation needs to be written
* @since 1.2
*/
public void toJson(Object src, Writer writer) {
if (src != null) {
toJson(src, src.getClass(), writer);
} else if (serializeNulls) {
writeOutNullString(writer);
public void toJson(Object src, Appendable writer) {
try {
if (src != null) {
toJson(src, src.getClass(), writer);
} else if (serializeNulls) {
writeOutNullString(writer);
}
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* This method serializes the specified object, including those of generic types, into its
* equivalent Json representation. This method must be used if the specified object is a generic
* type. For non-generic objects, use {@link #toJson(Object, Writer)} instead.
* type. For non-generic objects, use {@link #toJson(Object, Appendable)} instead.
*
* @param src the object for which JSON representation is to be created
* @param typeOfSrc The specific genericized type of src. You can obtain
@ -260,18 +263,22 @@ public final class Gson {
* @param writer Writer to which the Json representation of src needs to be written.
* @since 1.2
*/
public void toJson(Object src, Type typeOfSrc, Writer writer) {
if (src != null) {
JsonSerializationContext context = new JsonSerializationContextDefault(
createDefaultObjectNavigatorFactory(), serializeNulls, serializers);
JsonElement jsonElement = context.serialize(src, typeOfSrc);
public void toJson(Object src, Type typeOfSrc, Appendable writer) {
try {
if (src != null) {
JsonSerializationContext context = new JsonSerializationContextDefault(
createDefaultObjectNavigatorFactory(), serializeNulls, serializers);
JsonElement jsonElement = context.serialize(src, typeOfSrc);
//TODO(Joel): instead of navigating the "JsonElement" inside the formatter, do it here.
formatter.format(jsonElement, new PrintWriter(writer), serializeNulls);
} else {
if (serializeNulls) {
writeOutNullString(writer);
//TODO(Joel): instead of navigating the "JsonElement" inside the formatter, do it here.
formatter.format(jsonElement, writer, serializeNulls);
} else {
if (serializeNulls) {
writeOutNullString(writer);
}
}
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
@ -388,13 +395,8 @@ public final class Gson {
*
* @param writer the object to append the null value to
*/
private void writeOutNullString(Writer writer) {
try {
writer.append(NULL_STRING);
} catch (IOException e) {
// Should this be a different exception???
throw new JsonParseException(e);
}
private void writeOutNullString(Appendable writer) throws IOException {
writer.append(NULL_STRING);
}
@Override

View File

@ -16,7 +16,7 @@
package com.google.gson;
import java.io.PrintWriter;
import java.io.IOException;
/**
* Formats Json in a compact way eliminating all unnecessary whitespace.
@ -26,61 +26,64 @@ import java.io.PrintWriter;
final class JsonCompactFormatter implements JsonFormatter {
private static class FormattingVisitor implements JsonElementVisitor {
private final PrintWriter writer;
private final Appendable writer;
private final boolean serializeNulls;
FormattingVisitor(PrintWriter writer, boolean serializeNulls) {
FormattingVisitor(Appendable writer, boolean serializeNulls) {
this.writer = writer;
this.serializeNulls = serializeNulls;
}
public void visitPrimitive(JsonPrimitive primitive) {
public void visitPrimitive(JsonPrimitive primitive) throws IOException {
writer.append(primitive.toString());
}
public void visitNull() {
public void visitNull() throws IOException {
writer.append("null");
}
public void startArray(JsonArray array) {
public void startArray(JsonArray array) throws IOException {
writer.append('[');
}
public void visitArrayMember(JsonArray parent, JsonPrimitive member, boolean isFirst) {
public void visitArrayMember(JsonArray parent, JsonPrimitive member,
boolean isFirst) throws IOException {
if (!isFirst) {
writer.append(',');
}
writer.append(member.toString());
}
public void visitArrayMember(JsonArray parent, JsonArray member, boolean isFirst) {
public void visitArrayMember(JsonArray parent, JsonArray member,
boolean isFirst) throws IOException {
if (!isFirst) {
writer.append(',');
}
}
public void visitArrayMember(JsonArray parent, JsonObject member, boolean isFirst) {
public void visitArrayMember(JsonArray parent, JsonObject member,
boolean isFirst) throws IOException {
if (!isFirst) {
writer.append(',');
}
}
public void visitNullArrayMember(JsonArray parent, boolean isFirst) {
public void visitNullArrayMember(JsonArray parent, boolean isFirst) throws IOException {
if (!isFirst) {
writer.append(',');
}
}
public void endArray(JsonArray array) {
public void endArray(JsonArray array) throws IOException {
writer.append(']');
}
public void startObject(JsonObject object) {
public void startObject(JsonObject object) throws IOException {
writer.append('{');
}
public void visitObjectMember(JsonObject parent, String memberName, JsonPrimitive member,
boolean isFirst) {
boolean isFirst) throws IOException {
if (!isFirst) {
writer.append(',');
}
@ -91,7 +94,7 @@ final class JsonCompactFormatter implements JsonFormatter {
}
public void visitObjectMember(JsonObject parent, String memberName, JsonArray member,
boolean isFirst) {
boolean isFirst) throws IOException {
if (!isFirst) {
writer.append(',');
}
@ -101,7 +104,7 @@ final class JsonCompactFormatter implements JsonFormatter {
}
public void visitObjectMember(JsonObject parent, String memberName, JsonObject member,
boolean isFirst) {
boolean isFirst) throws IOException {
if (!isFirst) {
writer.append(',');
}
@ -110,18 +113,20 @@ final class JsonCompactFormatter implements JsonFormatter {
writer.append("\":");
}
public void visitNullObjectMember(JsonObject parent, String memberName, boolean isFirst) {
public void visitNullObjectMember(JsonObject parent, String memberName,
boolean isFirst) throws IOException {
if (serializeNulls) {
visitObjectMember(parent, memberName, (JsonObject) null, isFirst);
}
}
public void endObject(JsonObject object) {
public void endObject(JsonObject object) throws IOException {
writer.append('}');
}
}
public void format(JsonElement root, PrintWriter writer, boolean serializeNulls) {
public void format(JsonElement root, Appendable writer,
boolean serializeNulls) throws IOException {
if (root == null) {
return;
}

View File

@ -16,27 +16,32 @@
package com.google.gson;
import java.io.IOException;
/**
* Definition of a visitor for a JsonElement tree.
*
* @author Inderjeet Singh
*/
interface JsonElementVisitor {
void visitPrimitive(JsonPrimitive primitive);
void visitNull();
void visitPrimitive(JsonPrimitive primitive) throws IOException;
void visitNull() throws IOException;
void startArray(JsonArray array);
void visitArrayMember(JsonArray parent, JsonPrimitive member, boolean isFirst);
void visitArrayMember(JsonArray parent, JsonArray member, boolean isFirst);
void visitArrayMember(JsonArray parent, JsonObject member, boolean isFirst);
void visitNullArrayMember(JsonArray parent, boolean isFirst);
void endArray(JsonArray array);
void startArray(JsonArray array) throws IOException;
void visitArrayMember(JsonArray parent, JsonPrimitive member, boolean isFirst) throws IOException;
void visitArrayMember(JsonArray parent, JsonArray member, boolean isFirst) throws IOException;
void visitArrayMember(JsonArray parent, JsonObject member, boolean isFirst) throws IOException;
void visitNullArrayMember(JsonArray parent, boolean isFirst) throws IOException;
void endArray(JsonArray array) throws IOException;
void startObject(JsonObject object);
void startObject(JsonObject object) throws IOException;
void visitObjectMember(JsonObject parent, String memberName, JsonPrimitive member,
boolean isFirst);
void visitObjectMember(JsonObject parent, String memberName, JsonArray member, boolean isFirst);
void visitObjectMember(JsonObject parent, String memberName, JsonObject member, boolean isFirst);
void visitNullObjectMember(JsonObject parent, String memberName, boolean isFirst);
void endObject(JsonObject object);
boolean isFirst) throws IOException;
void visitObjectMember(JsonObject parent, String memberName, JsonArray member,
boolean isFirst) throws IOException;
void visitObjectMember(JsonObject parent, String memberName, JsonObject member,
boolean isFirst) throws IOException;
void visitNullObjectMember(JsonObject parent, String memberName,
boolean isFirst) throws IOException;
void endObject(JsonObject object) throws IOException;
}

View File

@ -16,6 +16,8 @@
package com.google.gson;
import java.io.IOException;
/**
* Performs JSON escaping and passes on the new escaped value to the delegate
* {@link JsonElementVisitor}.
@ -34,18 +36,19 @@ class JsonEscapingVisitor extends DelegatingJsonElementVisitor {
}
@Override
public void visitArrayMember(JsonArray parent, JsonPrimitive member, boolean isFirst) {
public void visitArrayMember(JsonArray parent, JsonPrimitive member,
boolean isFirst) throws IOException {
super.visitArrayMember(parent, escapeJsonPrimitive(member), isFirst);
}
@Override
public void visitObjectMember(
JsonObject parent, String memberName, JsonPrimitive member, boolean isFirst) {
public void visitObjectMember(JsonObject parent, String memberName, JsonPrimitive member,
boolean isFirst) throws IOException {
super.visitObjectMember(parent, memberName, escapeJsonPrimitive(member), isFirst);
}
@Override
public void visitPrimitive(JsonPrimitive primitive) {
public void visitPrimitive(JsonPrimitive primitive) throws IOException {
super.visitPrimitive(escapeJsonPrimitive(primitive));
}

View File

@ -16,7 +16,7 @@
package com.google.gson;
import java.io.PrintWriter;
import java.io.IOException;
/**
* Common interface for a formatter for Json.
@ -33,5 +33,6 @@ interface JsonFormatter {
* @param writer the writer to output the formatter JSON to.
* @param serializeNulls serialize null values in the output.
*/
public void format(JsonElement root, PrintWriter writer, boolean serializeNulls);
public void format(JsonElement root, Appendable writer,
boolean serializeNulls) throws IOException;
}

View File

@ -16,7 +16,7 @@
package com.google.gson;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@ -48,10 +48,10 @@ final class JsonPrintFormatter implements JsonFormatter {
}
private class JsonWriter {
private final PrintWriter writer;
private final Appendable writer;
private StringBuilder line;
private int level;
JsonWriter(PrintWriter writer) {
JsonWriter(Appendable writer) {
this.writer = writer;
level = 0;
line = new StringBuilder();
@ -67,17 +67,17 @@ final class JsonPrintFormatter implements JsonFormatter {
getLine().append(value);
}
void fieldSeparator() {
void fieldSeparator() throws IOException {
getLine().append(':');
breakLineIfNeeded();
}
void elementSeparator() {
void elementSeparator() throws IOException {
getLine().append(',');
breakLineIfNeeded();
}
void beginObject() {
void beginObject() throws IOException {
++level;
breakLineIfNeeded();
getLine().append('{');
@ -88,7 +88,7 @@ final class JsonPrintFormatter implements JsonFormatter {
--level;
}
void beginArray() {
void beginArray() throws IOException {
++level;
breakLineIfNeeded();
getLine().append('[');
@ -99,13 +99,13 @@ final class JsonPrintFormatter implements JsonFormatter {
--level;
}
private void breakLineIfNeeded() {
private void breakLineIfNeeded() throws IOException {
if (getLine().length() > printMargin - rightMargin) {
finishLine();
}
}
private void finishLine() {
private void finishLine() throws IOException {
if (line != null) {
writer.append(line).append("\n");
}
@ -143,7 +143,7 @@ final class JsonPrintFormatter implements JsonFormatter {
this.firstObjectMember = new HashMap<Integer, Boolean>();
}
private void addCommaCheckingFirst(Map<Integer, Boolean> first) {
private void addCommaCheckingFirst(Map<Integer, Boolean> first) throws IOException {
if (first.get(level) != Boolean.FALSE) {
first.put(level, false);
} else {
@ -151,25 +151,28 @@ final class JsonPrintFormatter implements JsonFormatter {
}
}
public void startArray(JsonArray array) {
public void startArray(JsonArray array) throws IOException {
firstArrayElement.put(++level, true);
writer.beginArray();
}
public void visitArrayMember(JsonArray parent, JsonPrimitive member, boolean isFirst) {
public void visitArrayMember(JsonArray parent, JsonPrimitive member,
boolean isFirst) throws IOException {
addCommaCheckingFirst(firstArrayElement);
writer.value(member.toString());
}
public void visitArrayMember(JsonArray parent, JsonArray member, boolean first) {
public void visitArrayMember(JsonArray parent, JsonArray member,
boolean first) throws IOException {
addCommaCheckingFirst(firstArrayElement);
}
public void visitArrayMember(JsonArray parent, JsonObject member, boolean first) {
public void visitArrayMember(JsonArray parent, JsonObject member,
boolean first) throws IOException {
addCommaCheckingFirst(firstArrayElement);
}
public void visitNullArrayMember(JsonArray parent, boolean isFirst) {
public void visitNullArrayMember(JsonArray parent, boolean isFirst) throws IOException {
addCommaCheckingFirst(firstArrayElement);
}
@ -178,13 +181,13 @@ final class JsonPrintFormatter implements JsonFormatter {
writer.endArray();
}
public void startObject(JsonObject object) {
public void startObject(JsonObject object) throws IOException {
firstObjectMember.put(level, true);
writer.beginObject();
}
public void visitObjectMember(JsonObject parent, String memberName, JsonPrimitive member,
boolean isFirst) {
boolean isFirst) throws IOException {
addCommaCheckingFirst(firstObjectMember);
writer.key(memberName);
writer.fieldSeparator();
@ -192,20 +195,21 @@ final class JsonPrintFormatter implements JsonFormatter {
}
public void visitObjectMember(JsonObject parent, String memberName, JsonArray member,
boolean isFirst) {
boolean isFirst) throws IOException {
addCommaCheckingFirst(firstObjectMember);
writer.key(memberName);
writer.fieldSeparator();
}
public void visitObjectMember(JsonObject parent, String memberName, JsonObject member,
boolean isFirst) {
boolean isFirst) throws IOException {
addCommaCheckingFirst(firstObjectMember);
writer.key(memberName);
writer.fieldSeparator();
}
public void visitNullObjectMember(JsonObject parent, String memberName, boolean isFirst) {
public void visitNullObjectMember(JsonObject parent, String memberName,
boolean isFirst) throws IOException {
if (serializeNulls) {
visitObjectMember(parent, memberName, (JsonObject) null, isFirst);
}
@ -224,7 +228,8 @@ final class JsonPrintFormatter implements JsonFormatter {
}
}
public void format(JsonElement root, PrintWriter writer, boolean serializeNulls) {
public void format(JsonElement root, Appendable writer,
boolean serializeNulls) throws IOException {
if (root == null) {
return;
}

View File

@ -16,6 +16,7 @@
package com.google.gson;
import java.io.IOException;
import java.util.Map;
/**
@ -32,7 +33,7 @@ final class JsonTreeNavigator {
this.visitNulls = visitNulls;
}
public void navigate(JsonElement element) {
public void navigate(JsonElement element) throws IOException {
if (element == null || element.isJsonNull()) {
visitor.visitNull();
} else if (element.isJsonArray()) {
@ -66,7 +67,7 @@ final class JsonTreeNavigator {
* Returns true if the child was visited, false if it was skipped.
*/
private boolean visitChild(JsonObject parent, String childName, JsonElement child,
boolean isFirst) {
boolean isFirst) throws IOException {
if (child != null) {
if (child.isJsonNull()) {
if (visitNulls) {
@ -93,7 +94,7 @@ final class JsonTreeNavigator {
/**
* Returns true if the child was visited, false if it was skipped.
*/
private void visitChild(JsonArray parent, JsonElement child, boolean isFirst) {
private void visitChild(JsonArray parent, JsonElement child, boolean isFirst) throws IOException {
if (child == null || child.isJsonNull()) {
visitor.visitNullArrayMember(parent, isFirst);
navigate(null);