From f602bce9f536df971b8bfa01b7ffb111e2896c97 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Sat, 3 Dec 2011 19:46:25 +0000 Subject: [PATCH] Nice documentation for TypeAdapter. --- .../RuntimeTypeAdapterFactory.java | 8 +- gson/src/main/java/com/google/gson/Gson.java | 50 +-- .../com/google/gson/JsonDeserializer.java | 3 + .../java/com/google/gson/JsonSerializer.java | 3 + .../java/com/google/gson/TreeTypeAdapter.java | 14 +- .../java/com/google/gson/TypeAdapter.java | 329 +++++++++++++-- .../com/google/gson/internal/Excluder.java | 12 +- .../gson/internal/bind/ArrayTypeAdapter.java | 24 +- .../internal/bind/BigDecimalTypeAdapter.java | 12 +- .../internal/bind/BigIntegerTypeAdapter.java | 12 +- .../bind/CollectionTypeAdapterFactory.java | 24 +- .../gson/internal/bind/DateTypeAdapter.java | 14 +- .../internal/bind/MapTypeAdapterFactory.java | 64 +-- .../gson/internal/bind/ObjectTypeAdapter.java | 38 +- .../bind/ReflectiveTypeAdapterFactory.java | 30 +- .../internal/bind/SqlDateTypeAdapter.java | 12 +- .../gson/internal/bind/TimeTypeAdapter.java | 12 +- .../bind/TypeAdapterRuntimeTypeWrapper.java | 8 +- .../gson/internal/bind/TypeAdapters.java | 374 +++++++++--------- .../functional/StreamingTypeAdaptersTest.java | 8 +- .../functional/TypeAdapterPrecedenceTest.java | 8 +- 21 files changed, 673 insertions(+), 386 deletions(-) diff --git a/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java b/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java index 7d542498..c788ef54 100644 --- a/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java +++ b/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java @@ -195,8 +195,8 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapter.Factory { } return new TypeAdapter() { - @Override public T read(JsonReader reader) throws IOException { - JsonElement jsonElement = Streams.parse(reader); + @Override public T read(JsonReader in) throws IOException { + JsonElement jsonElement = Streams.parse(in); JsonElement labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName); if (labelJsonElement == null) { throw new JsonParseException("cannot deserialize " + baseType @@ -212,7 +212,7 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapter.Factory { return delegate.fromJsonTree(jsonElement); } - @Override public void write(JsonWriter writer, T value) throws IOException { + @Override public void write(JsonWriter out, T value) throws IOException { Class srcType = value.getClass(); String label = subtypeToLabel.get(srcType); @SuppressWarnings("unchecked") // registration requires that subtype extends T @@ -231,7 +231,7 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapter.Factory { for (Map.Entry e : jsonObject.entrySet()) { clone.add(e.getKey(), e.getValue()); } - Streams.write(clone, writer); + Streams.write(clone, out); } }; } diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index 3f68535d..4ba56176 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -251,21 +251,21 @@ public final class Gson { return TypeAdapters.DOUBLE; } return new TypeAdapter() { - @Override public Double read(JsonReader reader) throws IOException { - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); + @Override public Double read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); return null; } - return reader.nextDouble(); + return in.nextDouble(); } - @Override public void write(JsonWriter writer, Number value) throws IOException { + @Override public void write(JsonWriter out, Number value) throws IOException { if (value == null) { - writer.nullValue(); + out.nullValue(); return; } double doubleValue = value.doubleValue(); checkValidFloatingPoint(doubleValue); - writer.value(value); + out.value(value); } }; } @@ -275,21 +275,21 @@ public final class Gson { return TypeAdapters.FLOAT; } return new TypeAdapter() { - @Override public Float read(JsonReader reader) throws IOException { - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); + @Override public Float read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); return null; } - return (float) reader.nextDouble(); + return (float) in.nextDouble(); } - @Override public void write(JsonWriter writer, Number value) throws IOException { + @Override public void write(JsonWriter out, Number value) throws IOException { if (value == null) { - writer.nullValue(); + out.nullValue(); return; } float floatValue = value.floatValue(); checkValidFloatingPoint(floatValue); - writer.value(value); + out.value(value); } }; } @@ -307,19 +307,19 @@ public final class Gson { return TypeAdapters.LONG; } return new TypeAdapter() { - @Override public Number read(JsonReader reader) throws IOException { - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); + @Override public Number read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); return null; } - return reader.nextLong(); + return in.nextLong(); } - @Override public void write(JsonWriter writer, Number value) throws IOException { + @Override public void write(JsonWriter out, Number value) throws IOException { if (value == null) { - writer.nullValue(); + out.nullValue(); return; } - writer.value(value.toString()); + out.value(value.toString()); } }; } @@ -828,18 +828,18 @@ public final class Gson { delegate = typeAdapter; } - @Override public T read(JsonReader reader) throws IOException { + @Override public T read(JsonReader in) throws IOException { if (delegate == null) { throw new IllegalStateException(); } - return delegate.read(reader); + return delegate.read(in); } - @Override public void write(JsonWriter writer, T value) throws IOException { + @Override public void write(JsonWriter out, T value) throws IOException { if (delegate == null) { throw new IllegalStateException(); } - delegate.write(writer, value); + delegate.write(out, value); } } diff --git a/gson/src/main/java/com/google/gson/JsonDeserializer.java b/gson/src/main/java/com/google/gson/JsonDeserializer.java index 81d0b3cd..0589eb28 100644 --- a/gson/src/main/java/com/google/gson/JsonDeserializer.java +++ b/gson/src/main/java/com/google/gson/JsonDeserializer.java @@ -61,6 +61,9 @@ import java.lang.reflect.Type; * Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdDeserializer()).create(); * * + *

New applications should prefer {@link TypeAdapter}, whose streaming API + * is more efficient than this interface's tree API. + * * @author Inderjeet Singh * @author Joel Leitch * diff --git a/gson/src/main/java/com/google/gson/JsonSerializer.java b/gson/src/main/java/com/google/gson/JsonSerializer.java index 81f79741..a6050033 100644 --- a/gson/src/main/java/com/google/gson/JsonSerializer.java +++ b/gson/src/main/java/com/google/gson/JsonSerializer.java @@ -60,6 +60,9 @@ import java.lang.reflect.Type; * Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdSerializer()).create(); * * + *

New applications should prefer {@link TypeAdapter}, whose streaming API + * is more efficient than this interface's tree API. + * * @author Inderjeet Singh * @author Joel Leitch * diff --git a/gson/src/main/java/com/google/gson/TreeTypeAdapter.java b/gson/src/main/java/com/google/gson/TreeTypeAdapter.java index 8521de54..1b18582e 100644 --- a/gson/src/main/java/com/google/gson/TreeTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/TreeTypeAdapter.java @@ -47,28 +47,28 @@ final class TreeTypeAdapter extends TypeAdapter { this.skipPast = skipPast; } - @Override public T read(JsonReader reader) throws IOException { + @Override public T read(JsonReader in) throws IOException { if (deserializer == null) { - return delegate().read(reader); + return delegate().read(in); } - JsonElement value = Streams.parse(reader); + JsonElement value = Streams.parse(in); if (value.isJsonNull()) { return null; } return deserializer.deserialize(value, typeToken.getType(), gson.deserializationContext); } - @Override public void write(JsonWriter writer, T value) throws IOException { + @Override public void write(JsonWriter out, T value) throws IOException { if (serializer == null) { - delegate().write(writer, value); + delegate().write(out, value); return; } if (value == null) { - writer.nullValue(); + out.nullValue(); return; } JsonElement tree = serializer.serialize(value, typeToken.getType(), gson.serializationContext); - Streams.write(tree,writer); + Streams.write(tree, out); } private TypeAdapter delegate() { diff --git a/gson/src/main/java/com/google/gson/TypeAdapter.java b/gson/src/main/java/com/google/gson/TypeAdapter.java index 81c8c316..8f743727 100644 --- a/gson/src/main/java/com/google/gson/TypeAdapter.java +++ b/gson/src/main/java/com/google/gson/TypeAdapter.java @@ -16,8 +16,8 @@ package com.google.gson; -import com.google.gson.internal.bind.JsonTreeReader; import com.google.gson.internal.bind.JsonElementWriter; +import com.google.gson.internal.bind.JsonTreeReader; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; @@ -27,51 +27,188 @@ import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; -// TODO: nice documentation - /** + * Converts between Java objects and JSON. Applications use type adapters both + * for customizing types' JSON forms, and for JSON conversions. + * + *

Defining a type's JSON form

+ * By default Gson converts application classes to JSON using its built-in type + * adapters. Change your Java objects' JSON representation by subclassing {@code + * TypeAdapter} and registering the subclass with a {@code GsonBuilder}. Here's + * an example of a type adapter for an (X,Y) coordinate point:
   {@code
+ *
+ *   public class PointAdapter extends TypeAdapter {
+ *     public Point read(JsonReader reader) throws IOException {
+ *       if (reader.peek() == JsonToken.NULL) {
+ *         reader.nextNull();
+ *         return null;
+ *       }
+ *       String xy = reader.nextString();
+ *       String[] parts = xy.split(",");
+ *       int x = Integer.parseInt(parts[0]);
+ *       int y = Integer.parseInt(parts[1]);
+ *       return new Point(x, y);
+ *     }
+ *     public void write(JsonWriter writer, Point value) throws IOException {
+ *       if (value == null) {
+ *         writer.nullValue();
+ *         return;
+ *       }
+ *       String xy = value.getX() + "," + value.getY();
+ *       writer.value(xy);
+ *     }
+ *   }}
+ * With this type adapter installed, Gson will convert {@code Points} to JSON as + * strings like {@code "5,8"} rather than objects like {@code {"x":5,"y":8}}. In + * this case the type adapter binds a rich Java class to a compact JSON value. + * + *

The {@link #read(JsonReader) read()} method must read exactly one value + * and {@link #write(JsonWriter,Object) write()} must write exactly one value. + * For primitive types this is means readers should make exactly one call to + * nextType() and writers should make exactly one call to + * one of value() or nullValue(). For composite types, + * type adapters should start with a call to beginType(), + * convert the entire contents of the object or array, and finish with a call + * to endType(). Failing to convert a value or converting + * too many values will disrupt the cadence of the caller and may cause the + * application to crash. + * + *

Type adapters should be prepared to read null from the stream and write it + * to the stream. If your {@code Gson} instance has been configured to {@link + * GsonBuilder#serializeNulls()}, these will be written to the final document. + * Otherwise the value (and the corresponding name when writing to a JSON + * object) will be omitted automatically. In either case your type adapter must + * handle null. + * + *

To use a custom type adapter with Gson, you must register it with a + * {@link GsonBuilder}:

   {@code
+ *
+ *   GsonBuilder builder = new GsonBuilder();
+ *   builder.registerTypeAdapter(Point.class, new PointAdapter());
+ *   ...
+ *   Gson gson = builder.create();
+ * }
+ * + *

JSON Conversion

+ *

Retrieve a type adapter from a {@code Gson} instance to deserialize a JSON + * document into a Java object:

   {@code
+ *
+ *   String json = "{'origin':'0,0','points':['1,2','3,4']}";
+ *   TypeAdapter graphAdapter = gson.getAdapter(Graph.class);
+ *   Graph graph = graphAdapter.fromJson(json);
+ * }
+ * ...or serialize a Java object to a JSON document:
   {@code
+ *
+ *   Graph graph = new Graph(...);
+ *   TypeAdapter graphAdapter = gson.getAdapter(Graph.class);
+ *   String json = graphAdapter.toJson(graph);
+ * }
+ * + *

Type adapters are type-specific. For example, a {@code + * TypeAdapter} can convert {@code Date} instances to JSON and JSON to + * instances of {@code Date}, but cannot convert any other types. * * @since 2.1 */ public abstract class TypeAdapter { - public abstract T read(JsonReader reader) throws IOException; - public abstract void write(JsonWriter writer, T value) throws IOException; + /** + * Writes one JSON value (an array, object, string, number, boolean or null) + * for {@code value}. + * + * @param value the Java object to write. May be null. + */ + public abstract void write(JsonWriter out, T value) throws IOException; + + /** + * Converts {@code value} to a JSON document and writes it to {@code out}. + * Unlike Gson's similar {@link Gson#toJson(JsonElement, Appendable) toJson} + * method, this write is strict. Create a {@link + * JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call + * {@link #write(com.google.gson.stream.JsonWriter, Object)} for lenient + * writing. + * + * @param value the Java object to convert. May be null. + */ + public final void toJson(Writer out, T value) throws IOException { + JsonWriter writer = new JsonWriter(out); + write(writer, value); + } + + /** + * Converts {@code value} to a JSON document. Unlike Gson's similar {@link + * Gson#toJson(Object) toJson} method, this write is strict. Create a {@link + * JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call + * {@link #write(com.google.gson.stream.JsonWriter, Object)} for lenient + * writing. + * + * @param value the Java object to convert. May be null. + */ public final String toJson(T value) throws IOException { StringWriter stringWriter = new StringWriter(); toJson(stringWriter, value); return stringWriter.toString(); } - public final void toJson(Writer out, T value) throws IOException { - JsonWriter writer = new JsonWriter(out); - write(writer, value); - } - - public final T fromJson(String json) throws IOException { - return fromJson(new StringReader(json)); - } - - public final T fromJson(Reader in) throws IOException { - JsonReader reader = new JsonReader(in); - reader.setLenient(true); - return read(reader); - } - - public JsonElement toJsonTree(T src) { + /** + * Converts {@code value} to a JSON tree. + * + * @param value the Java object to convert. May be null. + * @return the converted JSON tree. May be {@link JsonNull}. + */ + public JsonElement toJsonTree(T value) { try { JsonElementWriter jsonWriter = new JsonElementWriter(); jsonWriter.setLenient(true); - write(jsonWriter, src); + write(jsonWriter, value); return jsonWriter.get(); } catch (IOException e) { throw new JsonIOException(e); } } - public T fromJsonTree(JsonElement json) { + /** + * Reads one JSON value (an array, object, string, number, boolean or null) + * and converts it to a Java object. Returns the converted object. + * + * @return the converted Java object. May be null. + */ + public abstract T read(JsonReader in) throws IOException; + + /** + * Converts the JSON document in {@code in} to a Java object. Unlike Gson's + * similar {@link Gson#fromJson(java.io.Reader, Class) fromJson} method, this + * read is strict. Create a {@link JsonReader#setLenient(boolean) lenient} + * {@code JsonReader} and call {@link #read(JsonReader)} for lenient reading. + * + * @return the converted Java object. May be null. + */ + public final T fromJson(Reader in) throws IOException { + JsonReader reader = new JsonReader(in); + reader.setLenient(true); // TODO: non-lenient? + return read(reader); + } + + /** + * Converts the JSON document in {@code json} to a Java object. Unlike Gson's + * similar {@link Gson#fromJson(String, Class) fromJson} method, this read is + * strict. Create a {@link JsonReader#setLenient(boolean) lenient} {@code + * JsonReader} and call {@link #read(JsonReader)} for lenient reading. + * + * @return the converted Java object. May be null. + */ + public final T fromJson(String json) throws IOException { + return fromJson(new StringReader(json)); + } + + /** + * Converts {@code jsonTree} to a Java object. + * + * @param jsonTree the Java object to convert. May be {@link JsonNull}. + */ + public T fromJsonTree(JsonElement jsonTree) { try { - JsonReader jsonReader = new JsonTreeReader(json); + JsonReader jsonReader = new JsonTreeReader(jsonTree); jsonReader.setLenient(true); return read(jsonReader); } catch (IOException e) { @@ -80,9 +217,153 @@ public abstract class TypeAdapter { } /** + * Creates type adapters for set of related types. Type adapter factories are + * most useful when several types share similar structure in their JSON form. + * + *

Example: Converting enums to lowercase

+ * In this example, we implement a factory that creates type adapters for all + * enums. The type adapters will write enums in lowercase, despite the fact + * that they're defined in {@code CONSTANT_CASE} in the corresponding Java + * model:
   {@code
+   *
+   *   public class LowercaseEnumTypeAdapterFactory implements TypeAdapter.Factory {
+   *     public  TypeAdapter create(Gson gson, TypeToken type) {
+   *       Class rawType = (Class) type.getRawType();
+   *       if (!rawType.isEnum()) {
+   *         return null;
+   *       }
+   *
+   *       final Map lowercaseToConstant = new HashMap();
+   *       for (T constant : rawType.getEnumConstants()) {
+   *         lowercaseToConstant.put(toLowercase(constant), constant);
+   *       }
+   *
+   *       return new TypeAdapter() {
+   *         public void write(JsonWriter out, T value) throws IOException {
+   *           if (value == null) {
+   *             out.nullValue();
+   *           } else {
+   *             out.value(toLowercase(value));
+   *           }
+   *         }
+   *
+   *         public T read(JsonReader reader) throws IOException {
+   *           if (reader.peek() == JsonToken.NULL) {
+   *             reader.nextNull();
+   *             return null;
+   *           } else {
+   *             return lowercaseToConstant.get(reader.nextString());
+   *           }
+   *         }
+   *       };
+   *     }
+   *
+   *     private String toLowercase(Object o) {
+   *       return o.toString().toLowerCase(Locale.US);
+   *     }
+   *   }
+   * }
+ * + *

Type adapter factories select which types they provide type adapters + * for. If a factory cannot support a given type, it must return null when + * that type is passed to {@link #create}. Factories should expect {@code + * create()} to be called on them for many types and should return null for + * most of those types. In the above example the factory returns null for + * calls to {@code create()} where {@code type} is not an enum. + * + *

A factory is typically called once per type, but the returned type + * adapter may be used many times. It is most efficient to do expensive work + * like reflection in {@code create()} so that the type adapter's {@code + * read()} and {@code write()} methods can be very fast. In this example the + * mapping from lowercase name to enum value is computed eagerly. + * + *

As with type adapters, factories must be registered with a {@link + * GsonBuilder} for them to take effect:

   {@code
+   *
+   *  GsonBuilder builder = new GsonBuilder();
+   *  builder.registerTypeAdapterFactory(new LowercaseEnumTypeAdapterFactory());
+   *  ...
+   *  Gson gson = builder.create();
+   * }
+ * If multiple factories support the same type, the factory registered earlier + * takes precedence. + * + *

Example: composing other type adapters

+ * In this example we implement a factory for Guava's {@code Multiset} + * collection type. The factory can be used to create type adapters for + * multisets of any element type: the type adapter for {@code + * Multiset} is different from the type adapter for {@code + * Multiset}. + * + *

The type adapter delegates to another type adapter for the + * multiset elements. It figures out the element type by reflecting on the + * multiset's type token. A {@code Gson} is passed in to {@code create} for + * just this purpose:

   {@code
+   *
+   *   public class MultisetTypeAdapterFactory implements TypeAdapter.Factory {
+   *     public  TypeAdapter create(Gson gson, TypeToken typeToken) {
+   *       Type type = typeToken.getType();
+   *       if (typeToken.getRawType() != Multiset.class
+   *           || !(type instanceof ParameterizedType)) {
+   *         return null;
+   *       }
+   *
+   *       Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
+   *       TypeAdapter elementAdapter = gson.getAdapter(TypeToken.get(elementType));
+   *       return (TypeAdapter) newMultisetAdapter(elementAdapter);
+   *     }
+   *
+   *     private  TypeAdapter> newMultisetAdapter(
+   *         final TypeAdapter elementAdapter) {
+   *       return new TypeAdapter>() {
+   *         public void write(JsonWriter out, Multiset value) throws IOException {
+   *           if (value == null) {
+   *             out.nullValue();
+   *             return;
+   *           }
+   *
+   *           out.beginArray();
+   *           for (Multiset.Entry entry : value.entrySet()) {
+   *             out.value(entry.getCount());
+   *             elementAdapter.write(out, entry.getElement());
+   *           }
+   *           out.endArray();
+   *         }
+   *
+   *         public Multiset read(JsonReader in) throws IOException {
+   *           if (in.peek() == JsonToken.NULL) {
+   *             in.nextNull();
+   *             return null;
+   *           }
+   *
+   *           Multiset result = LinkedHashMultiset.create();
+   *           in.beginArray();
+   *           while (in.hasNext()) {
+   *             int count = in.nextInt();
+   *             E element = elementAdapter.read(in);
+   *             result.add(element, count);
+   *           }
+   *           in.endArray();
+   *           return result;
+   *         }
+   *       };
+   *     }
+   *   }
+   * }
+ * Delegating from one type adapter to another is extremely powerful; it's + * the foundation of how Gson converts Java objects and collections. Whenever + * possible your factory should retrieve its delegate type adapter in the + * {@code create()} method; this ensures potentially-expensive type adapter + * creation happens only once. + * * @since 2.1 */ public interface Factory { + + /** + * Returns a type adapter for {@code type}, or null if this factory doesn't + * support {@code type}. + */ TypeAdapter create(Gson gson, TypeToken type); } } diff --git a/gson/src/main/java/com/google/gson/internal/Excluder.java b/gson/src/main/java/com/google/gson/internal/Excluder.java index 2b28ab5d..70dad864 100644 --- a/gson/src/main/java/com/google/gson/internal/Excluder.java +++ b/gson/src/main/java/com/google/gson/internal/Excluder.java @@ -120,20 +120,20 @@ public final class Excluder implements TypeAdapter.Factory, Cloneable { /** The delegate is lazily created because it may not be needed, and creating it may fail. */ private TypeAdapter delegate; - @Override public T read(JsonReader reader) throws IOException { + @Override public T read(JsonReader in) throws IOException { if (skipDeserialize) { - reader.skipValue(); + in.skipValue(); return null; } - return delegate().read(reader); + return delegate().read(in); } - @Override public void write(JsonWriter writer, T value) throws IOException { + @Override public void write(JsonWriter out, T value) throws IOException { if (skipSerialize) { - writer.nullValue(); + out.nullValue(); return; } - delegate().write(writer, value); + delegate().write(out, value); } private TypeAdapter delegate() { diff --git a/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java index 48ee91f4..6820a107 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java @@ -59,19 +59,19 @@ public final class ArrayTypeAdapter extends TypeAdapter { this.componentType = componentType; } - public Object read(JsonReader reader) throws IOException { - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); + public Object read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); return null; } List list = new ArrayList(); - reader.beginArray(); - while (reader.hasNext()) { - E instance = componentTypeAdapter.read(reader); + in.beginArray(); + while (in.hasNext()) { + E instance = componentTypeAdapter.read(in); list.add(instance); } - reader.endArray(); + in.endArray(); Object array = Array.newInstance(componentType, list.size()); for (int i = 0; i < list.size(); i++) { Array.set(array, i, list.get(i)); @@ -80,17 +80,17 @@ public final class ArrayTypeAdapter extends TypeAdapter { } @SuppressWarnings("unchecked") - @Override public void write(JsonWriter writer, Object array) throws IOException { + @Override public void write(JsonWriter out, Object array) throws IOException { if (array == null) { - writer.nullValue(); + out.nullValue(); return; } - writer.beginArray(); + out.beginArray(); for (int i = 0, length = Array.getLength(array); i < length; i++) { E value = (E) Array.get(array, i); - componentTypeAdapter.write(writer, value); + componentTypeAdapter.write(out, value); } - writer.endArray(); + out.endArray(); } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/BigDecimalTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/BigDecimalTypeAdapter.java index a728a63a..842812b0 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/BigDecimalTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/BigDecimalTypeAdapter.java @@ -33,20 +33,20 @@ import java.math.BigDecimal; public final class BigDecimalTypeAdapter extends TypeAdapter { @Override - public BigDecimal read(JsonReader reader) throws IOException { - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); + public BigDecimal read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); return null; } try { - return new BigDecimal(reader.nextString()); + return new BigDecimal(in.nextString()); } catch (NumberFormatException e) { throw new JsonSyntaxException(e); } } @Override - public void write(JsonWriter writer, BigDecimal value) throws IOException { - writer.value(value); + public void write(JsonWriter out, BigDecimal value) throws IOException { + out.value(value); } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/BigIntegerTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/BigIntegerTypeAdapter.java index e419b4c8..789e078a 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/BigIntegerTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/BigIntegerTypeAdapter.java @@ -32,20 +32,20 @@ import java.math.BigInteger; public final class BigIntegerTypeAdapter extends TypeAdapter { @Override - public BigInteger read(JsonReader reader) throws IOException { - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); + public BigInteger read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); return null; } try { - return new BigInteger(reader.nextString()); + return new BigInteger(in.nextString()); } catch (NumberFormatException e) { throw new JsonSyntaxException(e); } } @Override - public void write(JsonWriter writer, BigInteger value) throws IOException { - writer.value(value); + public void write(JsonWriter out, BigInteger value) throws IOException { + out.value(value); } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java index 82b21699..c635e279 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java +++ b/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java @@ -68,33 +68,33 @@ public final class CollectionTypeAdapterFactory implements TypeAdapter.Factory { this.constructor = constructor; } - public Collection read(JsonReader reader) throws IOException { - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); + public Collection read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); return null; } Collection collection = constructor.construct(); - reader.beginArray(); - while (reader.hasNext()) { - E instance = elementTypeAdapter.read(reader); + in.beginArray(); + while (in.hasNext()) { + E instance = elementTypeAdapter.read(in); collection.add(instance); } - reader.endArray(); + in.endArray(); return collection; } - public void write(JsonWriter writer, Collection collection) throws IOException { + public void write(JsonWriter out, Collection collection) throws IOException { if (collection == null) { - writer.nullValue(); // TODO: better policy here? + out.nullValue(); // TODO: better policy here? return; } - writer.beginArray(); + out.beginArray(); for (E element : collection) { - elementTypeAdapter.write(writer, element); + elementTypeAdapter.write(out, element); } - writer.endArray(); + out.endArray(); } } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java index 06328f1d..bb17a886 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/DateTypeAdapter.java @@ -57,12 +57,12 @@ public final class DateTypeAdapter extends TypeAdapter { return iso8601Format; } - @Override public Date read(JsonReader reader) throws IOException { - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); + @Override public Date read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); return null; } - return deserializeToDate(reader.nextString()); + return deserializeToDate(in.nextString()); } private synchronized Date deserializeToDate(String json) { @@ -81,12 +81,12 @@ public final class DateTypeAdapter extends TypeAdapter { } } - @Override public synchronized void write(JsonWriter writer, Date value) throws IOException { + @Override public synchronized void write(JsonWriter out, Date value) throws IOException { if (value == null) { - writer.nullValue(); + out.nullValue(); return; } String dateFormatAsString = enUsFormat.format(value); - writer.value(dateFormatAsString); + out.value(dateFormatAsString); } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java index 0920e72b..12b1fdf3 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java +++ b/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java @@ -156,57 +156,57 @@ public final class MapTypeAdapterFactory implements TypeAdapter.Factory { this.constructor = constructor; } - public Map read(JsonReader reader) throws IOException { - JsonToken peek = reader.peek(); + public Map read(JsonReader in) throws IOException { + JsonToken peek = in.peek(); if (peek == JsonToken.NULL) { - reader.nextNull(); + in.nextNull(); return null; } Map map = constructor.construct(); if (peek == JsonToken.BEGIN_ARRAY) { - reader.beginArray(); - while (reader.hasNext()) { - reader.beginArray(); // entry array - K key = keyTypeAdapter.read(reader); - V value = valueTypeAdapter.read(reader); + in.beginArray(); + while (in.hasNext()) { + in.beginArray(); // entry array + K key = keyTypeAdapter.read(in); + V value = valueTypeAdapter.read(in); V replaced = map.put(key, value); if (replaced != null) { throw new JsonSyntaxException("duplicate key: " + key); } - reader.endArray(); + in.endArray(); } - reader.endArray(); + in.endArray(); } else { - reader.beginObject(); - while (reader.hasNext()) { - JsonReaderInternalAccess.INSTANCE.promoteNameToValue(reader); - K key = keyTypeAdapter.read(reader); - V value = valueTypeAdapter.read(reader); + in.beginObject(); + while (in.hasNext()) { + JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in); + K key = keyTypeAdapter.read(in); + V value = valueTypeAdapter.read(in); V replaced = map.put(key, value); if (replaced != null) { throw new JsonSyntaxException("duplicate key: " + key); } } - reader.endObject(); + in.endObject(); } return map; } - public void write(JsonWriter writer, Map map) throws IOException { + public void write(JsonWriter out, Map map) throws IOException { if (map == null) { - writer.nullValue(); + out.nullValue(); return; } if (!complexMapKeySerialization) { - writer.beginObject(); + out.beginObject(); for (Map.Entry entry : map.entrySet()) { - writer.name(String.valueOf(entry.getKey())); - valueTypeAdapter.write(writer, entry.getValue()); + out.name(String.valueOf(entry.getKey())); + valueTypeAdapter.write(out, entry.getValue()); } - writer.endObject(); + out.endObject(); return; } @@ -222,22 +222,22 @@ public final class MapTypeAdapterFactory implements TypeAdapter.Factory { } if (hasComplexKeys) { - writer.beginArray(); + out.beginArray(); for (int i = 0; i < keys.size(); i++) { - writer.beginArray(); // entry array - Streams.write(keys.get(i), writer); - valueTypeAdapter.write(writer, values.get(i)); - writer.endArray(); + out.beginArray(); // entry array + Streams.write(keys.get(i), out); + valueTypeAdapter.write(out, values.get(i)); + out.endArray(); } - writer.endArray(); + out.endArray(); } else { - writer.beginObject(); + out.beginObject(); for (int i = 0; i < keys.size(); i++) { JsonElement keyElement = keys.get(i); - writer.name(keyToString(keyElement)); - valueTypeAdapter.write(writer, values.get(i)); + out.name(keyToString(keyElement)); + valueTypeAdapter.write(out, values.get(i)); } - writer.endObject(); + out.endObject(); } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java index ee7d1296..76e643d3 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java @@ -49,38 +49,38 @@ public final class ObjectTypeAdapter extends TypeAdapter { this.gson = gson; } - @Override public Object read(JsonReader reader) throws IOException { - JsonToken token = reader.peek(); + @Override public Object read(JsonReader in) throws IOException { + JsonToken token = in.peek(); switch (token) { case BEGIN_ARRAY: List list = new ArrayList(); - reader.beginArray(); - while (reader.hasNext()) { - list.add(read(reader)); + in.beginArray(); + while (in.hasNext()) { + list.add(read(in)); } - reader.endArray(); + in.endArray(); return list; case BEGIN_OBJECT: Map map = new LinkedHashMap(); - reader.beginObject(); - while (reader.hasNext()) { - map.put(reader.nextName(), read(reader)); + in.beginObject(); + while (in.hasNext()) { + map.put(in.nextName(), read(in)); } - reader.endObject(); + in.endObject(); return map; case STRING: - return reader.nextString(); + return in.nextString(); case NUMBER: - return reader.nextDouble(); + return in.nextDouble(); case BOOLEAN: - return reader.nextBoolean(); + return in.nextBoolean(); case NULL: - reader.nextNull(); + in.nextNull(); return null; } @@ -88,19 +88,19 @@ public final class ObjectTypeAdapter extends TypeAdapter { } @SuppressWarnings("unchecked") - @Override public void write(JsonWriter writer, Object value) throws IOException { + @Override public void write(JsonWriter out, Object value) throws IOException { if (value == null) { - writer.nullValue(); + out.nullValue(); return; } TypeAdapter typeAdapter = (TypeAdapter) gson.getAdapter(value.getClass()); if (typeAdapter instanceof ObjectTypeAdapter) { - writer.beginObject(); - writer.endObject(); + out.beginObject(); + out.endObject(); return; } - typeAdapter.write(writer, value); + typeAdapter.write(out, value); } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java index 36476e23..0a2b5c68 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java +++ b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java @@ -154,9 +154,9 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory { } @Override - public T read(JsonReader reader) throws IOException { - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); + public T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); return null; } @@ -165,15 +165,15 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory { // TODO: null out the other fields? try { - reader.beginObject(); - while (reader.hasNext()) { - String name = reader.nextName(); + in.beginObject(); + while (in.hasNext()) { + String name = in.nextName(); BoundField field = boundFields.get(name); if (field == null || !field.deserialized) { // TODO: define a better policy - reader.skipValue(); + in.skipValue(); } else { - field.read(reader, instance); + field.read(in, instance); } } } catch (IllegalStateException e) { @@ -181,29 +181,29 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory { } catch (IllegalAccessException e) { throw new AssertionError(e); } - reader.endObject(); + in.endObject(); return instance; } @Override - public void write(JsonWriter writer, T value) throws IOException { + public void write(JsonWriter out, T value) throws IOException { if (value == null) { - writer.nullValue(); // TODO: better policy here? + out.nullValue(); // TODO: better policy here? return; } - writer.beginObject(); + out.beginObject(); try { for (BoundField boundField : boundFields.values()) { if (boundField.serialized) { - writer.name(boundField.name); - boundField.write(writer, value); + out.name(boundField.name); + boundField.write(out, value); } } } catch (IllegalAccessException e) { throw new AssertionError(); } - writer.endObject(); + out.endObject(); } } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/SqlDateTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/SqlDateTypeAdapter.java index 87283d03..8a4c6582 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/SqlDateTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/SqlDateTypeAdapter.java @@ -46,13 +46,13 @@ public final class SqlDateTypeAdapter extends TypeAdapter { private final DateFormat format = new SimpleDateFormat("MMM d, yyyy"); @Override - public synchronized java.sql.Date read(JsonReader reader) throws IOException { - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); + public synchronized java.sql.Date read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); return null; } try { - final long utilDate = format.parse(reader.nextString()).getTime(); + final long utilDate = format.parse(in.nextString()).getTime(); return new java.sql.Date(utilDate); } catch (ParseException e) { throw new JsonSyntaxException(e); @@ -60,7 +60,7 @@ public final class SqlDateTypeAdapter extends TypeAdapter { } @Override - public synchronized void write(JsonWriter writer, java.sql.Date value) throws IOException { - writer.value(value == null ? null : format.format(value)); + public synchronized void write(JsonWriter out, java.sql.Date value) throws IOException { + out.value(value == null ? null : format.format(value)); } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/TimeTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/TimeTypeAdapter.java index e38a0b93..deaa6eac 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/TimeTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/TimeTypeAdapter.java @@ -46,20 +46,20 @@ public final class TimeTypeAdapter extends TypeAdapter