) graph.map.get(currentName);
- // now that we know the typeAdapter for this name, go from JsonElement to 'T'
- if (element.value == null) {
- element.typeAdapter = typeAdapter;
- element.read(graph);
- }
- return element.value;
- } finally {
- if (readEntireGraph) {
- graphThreadLocal.remove();
- }
- }
- }
- };
- }
-
- /**
- * Hook for the graph adapter to get a reference to a deserialized value
- * before that value is fully populated. This is useful to deserialize
- * values that directly or indirectly reference themselves: we can hand
- * out an instance before read() returns.
- *
- * Gson should only ever call this method when we're expecting it to;
- * that is only when we've called back into Gson to deserialize a tree.
- */
- @Override
- public Object createInstance(Type type) {
- Graph graph = graphThreadLocal.get();
- if (graph == null || graph.nextCreate == null) {
- throw new IllegalStateException("Unexpected call to createInstance() for " + type);
- }
- InstanceCreator> creator = instanceCreators.get(type);
- Object result = creator.createInstance(type);
- graph.nextCreate.value = result;
- graph.nextCreate = null;
- return result;
- }
- }
-
- static class Graph {
- /**
- * The graph elements. On serialization keys are objects (using an identity
- * hash map) and on deserialization keys are the string names (using a
- * standard hash map).
- */
- private final Map> map;
-
- /**
- * The queue of elements to write during serialization. Unused during
- * deserialization.
- */
- private final Queue> queue = new LinkedList<>();
-
- /**
- * The instance currently being deserialized. Used as a backdoor between
- * the graph traversal (which needs to know instances) and instance creators
- * which create them.
- */
- private Element nextCreate;
-
- private Graph(Map> map) {
- this.map = map;
- }
-
- /**
- * Returns a unique name for an element to be inserted into the graph.
- */
- public String nextName() {
- return "0x" + Integer.toHexString(map.size() + 1);
- }
- }
-
- /**
- * An element of the graph during serialization or deserialization.
- */
- static class Element {
- /**
- * This element's name in the top level graph object.
- */
- private final String id;
-
- /**
- * The value if known. During deserialization this is lazily populated.
- */
- private T value;
-
- /**
- * This element's type adapter if known. During deserialization this is
- * lazily populated.
- */
- private TypeAdapter typeAdapter;
-
- /**
- * The element to deserialize. Unused in serialization.
- */
- private final JsonElement element;
-
- Element(T value, String id, TypeAdapter typeAdapter, JsonElement element) {
- this.value = value;
- this.id = id;
- this.typeAdapter = typeAdapter;
- this.element = element;
- }
-
- void write(JsonWriter out) throws IOException {
- typeAdapter.write(out, value);
- }
-
- @SuppressWarnings("unchecked")
- void read(Graph graph) {
- if (graph.nextCreate != null) {
- throw new IllegalStateException("Unexpected recursive call to read() for " + id);
- }
- graph.nextCreate = (Element) this;
- value = typeAdapter.fromJsonTree(element);
- if (value == null) {
- throw new IllegalStateException("non-null value deserialized to null: " + element);
- }
- }
- }
-}
diff --git a/extras/src/main/java/com/google/gson/interceptors/Intercept.java b/extras/src/main/java/com/google/gson/interceptors/Intercept.java
deleted file mode 100644
index fef29cbf0b..0000000000
--- a/extras/src/main/java/com/google/gson/interceptors/Intercept.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc.
- *
- * 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.google.gson.interceptors;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-
-/**
- * Use this annotation to indicate various interceptors for class instances after
- * they have been processed by Gson. For example, you can use it to validate an instance
- * after it has been deserialized from Json.
- * Here is an example of how this annotation is used:
- * Here is an example of how this annotation is used:
- *
- * @Intercept(postDeserialize=UserValidator.class)
- * public class User {
- * String name;
- * String password;
- * String emailAddress;
- * }
- *
- * public class UserValidator implements JsonPostDeserializer<User> {
- * public void postDeserialize(User user) {
- * // Do some checks on user
- * if (user.name == null || user.password == null) {
- * throw new JsonParseException("name and password are required fields.");
- * }
- * if (user.emailAddress == null) {
- * emailAddress = "unknown"; // assign a default value.
- * }
- * }
- * }
- *
- *
- * @author Inderjeet Singh
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface Intercept {
-
- /**
- * Specify the class that provides the methods that should be invoked after an instance
- * has been deserialized.
- */
- @SuppressWarnings("rawtypes")
- public Class extends JsonPostDeserializer> postDeserialize();
-}
diff --git a/extras/src/main/java/com/google/gson/interceptors/InterceptorFactory.java b/extras/src/main/java/com/google/gson/interceptors/InterceptorFactory.java
deleted file mode 100644
index 51916c220d..0000000000
--- a/extras/src/main/java/com/google/gson/interceptors/InterceptorFactory.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.google.gson.interceptors;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.TypeAdapterFactory;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-import java.io.IOException;
-
-/**
- * A type adapter factory that implements {@code @Intercept}.
- */
-public final class InterceptorFactory implements TypeAdapterFactory {
- @Override public TypeAdapter create(Gson gson, TypeToken type) {
- Intercept intercept = type.getRawType().getAnnotation(Intercept.class);
- if (intercept == null) {
- return null;
- }
-
- TypeAdapter delegate = gson.getDelegateAdapter(this, type);
- return new InterceptorAdapter<>(delegate, intercept);
- }
-
- static class InterceptorAdapter extends TypeAdapter {
- private final TypeAdapter delegate;
- private final JsonPostDeserializer postDeserializer;
-
- @SuppressWarnings("unchecked") // ?
- public InterceptorAdapter(TypeAdapter delegate, Intercept intercept) {
- try {
- this.delegate = delegate;
- this.postDeserializer = intercept.postDeserialize().newInstance();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override public void write(JsonWriter out, T value) throws IOException {
- delegate.write(out, value);
- }
-
- @Override public T read(JsonReader in) throws IOException {
- T result = delegate.read(in);
- postDeserializer.postDeserialize(result);
- return result;
- }
- }
-}
diff --git a/extras/src/main/java/com/google/gson/interceptors/JsonPostDeserializer.java b/extras/src/main/java/com/google/gson/interceptors/JsonPostDeserializer.java
deleted file mode 100644
index 0f3a72ca82..0000000000
--- a/extras/src/main/java/com/google/gson/interceptors/JsonPostDeserializer.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc.
- *
- * 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.google.gson.interceptors;
-
-import com.google.gson.InstanceCreator;
-
-/**
- * This interface is implemented by a class that wishes to inspect or modify an object
- * after it has been deserialized. You must define a no-args constructor or register an
- * {@link InstanceCreator} for such a class.
- *
- * @author Inderjeet Singh
- */
-public interface JsonPostDeserializer {
-
- /**
- * This method is called by Gson after the object has been deserialized from Json.
- */
- public void postDeserialize(T object);
-}
diff --git a/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java b/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java
deleted file mode 100644
index 450ebbab2d..0000000000
--- a/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2016 Gson Authors
- *
- * 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.google.gson.typeadapters;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import javax.annotation.PostConstruct;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.TypeAdapterFactory;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-
-public class PostConstructAdapterFactory implements TypeAdapterFactory {
- // copied from https://gist.github.com/swankjesse/20df26adaf639ed7fd160f145a0b661a
- @Override
- public TypeAdapter create(Gson gson, TypeToken type) {
- for (Class> t = type.getRawType(); (t != Object.class) && (t.getSuperclass() != null); t = t.getSuperclass()) {
- for (Method m : t.getDeclaredMethods()) {
- if (m.isAnnotationPresent(PostConstruct.class)) {
- m.setAccessible(true);
- TypeAdapter delegate = gson.getDelegateAdapter(this, type);
- return new PostConstructAdapter<>(delegate, m);
- }
- }
- }
- return null;
- }
-
- final static class PostConstructAdapter extends TypeAdapter {
- private final TypeAdapter delegate;
- private final Method method;
-
- public PostConstructAdapter(TypeAdapter delegate, Method method) {
- this.delegate = delegate;
- this.method = method;
- }
-
- @Override public T read(JsonReader in) throws IOException {
- T result = delegate.read(in);
- if (result != null) {
- try {
- method.invoke(result);
- } catch (IllegalAccessException e) {
- throw new AssertionError();
- } catch (InvocationTargetException e) {
- if (e.getCause() instanceof RuntimeException) throw (RuntimeException) e.getCause();
- throw new RuntimeException(e.getCause());
- }
- }
- return result;
- }
-
- @Override public void write(JsonWriter out, T value) throws IOException {
- delegate.write(out, value);
- }
- }
-}
diff --git a/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java b/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java
deleted file mode 100644
index 87b522f0c4..0000000000
--- a/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * 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.google.gson.typeadapters;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.TypeAdapter;
-import com.google.gson.TypeAdapterFactory;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-import java.io.IOException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * Adapts values whose runtime type may differ from their declaration type. This
- * is necessary when a field's type is not the same type that GSON should create
- * when deserializing that field. For example, consider these types:
- * {@code
- * abstract class Shape {
- * int x;
- * int y;
- * }
- * class Circle extends Shape {
- * int radius;
- * }
- * class Rectangle extends Shape {
- * int width;
- * int height;
- * }
- * class Diamond extends Shape {
- * int width;
- * int height;
- * }
- * class Drawing {
- * Shape bottomShape;
- * Shape topShape;
- * }
- * }
- * Without additional type information, the serialized JSON is ambiguous. Is
- * the bottom shape in this drawing a rectangle or a diamond?
{@code
- * {
- * "bottomShape": {
- * "width": 10,
- * "height": 5,
- * "x": 0,
- * "y": 0
- * },
- * "topShape": {
- * "radius": 2,
- * "x": 4,
- * "y": 1
- * }
- * }}
- * This class addresses this problem by adding type information to the
- * serialized JSON and honoring that type information when the JSON is
- * deserialized: {@code
- * {
- * "bottomShape": {
- * "type": "Diamond",
- * "width": 10,
- * "height": 5,
- * "x": 0,
- * "y": 0
- * },
- * "topShape": {
- * "type": "Circle",
- * "radius": 2,
- * "x": 4,
- * "y": 1
- * }
- * }}
- * Both the type field name ({@code "type"}) and the type labels ({@code
- * "Rectangle"}) are configurable.
- *
- * Registering Types
- * Create a {@code RuntimeTypeAdapterFactory} by passing the base type and type field
- * name to the {@link #of} factory method. If you don't supply an explicit type
- * field name, {@code "type"} will be used. {@code
- * RuntimeTypeAdapterFactory shapeAdapterFactory
- * = RuntimeTypeAdapterFactory.of(Shape.class, "type");
- * }
- * Next register all of your subtypes. Every subtype must be explicitly
- * registered. This protects your application from injection attacks. If you
- * don't supply an explicit type label, the type's simple name will be used.
- * {@code
- * shapeAdapterFactory.registerSubtype(Rectangle.class, "Rectangle");
- * shapeAdapterFactory.registerSubtype(Circle.class, "Circle");
- * shapeAdapterFactory.registerSubtype(Diamond.class, "Diamond");
- * }
- * Finally, register the type adapter factory in your application's GSON builder:
- * {@code
- * Gson gson = new GsonBuilder()
- * .registerTypeAdapterFactory(shapeAdapterFactory)
- * .create();
- * }
- * Like {@code GsonBuilder}, this API supports chaining: {@code
- * RuntimeTypeAdapterFactory shapeAdapterFactory = RuntimeTypeAdapterFactory.of(Shape.class)
- * .registerSubtype(Rectangle.class)
- * .registerSubtype(Circle.class)
- * .registerSubtype(Diamond.class);
- * }
- *
- * Serialization and deserialization
- * In order to serialize and deserialize a polymorphic object,
- * you must specify the base type explicitly.
- * {@code
- * Diamond diamond = new Diamond();
- * String json = gson.toJson(diamond, Shape.class);
- * }
- * And then:
- * {@code
- * Shape shape = gson.fromJson(json, Shape.class);
- * }
- */
-public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory {
- private final Class> baseType;
- private final String typeFieldName;
- private final Map> labelToSubtype = new LinkedHashMap<>();
- private final Map, String> subtypeToLabel = new LinkedHashMap<>();
- private final boolean maintainType;
- private boolean recognizeSubtypes;
-
- private RuntimeTypeAdapterFactory(
- Class> baseType, String typeFieldName, boolean maintainType) {
- if (typeFieldName == null || baseType == null) {
- throw new NullPointerException();
- }
- this.baseType = baseType;
- this.typeFieldName = typeFieldName;
- this.maintainType = maintainType;
- }
-
- /**
- * Creates a new runtime type adapter using for {@code baseType} using {@code
- * typeFieldName} as the type field name. Type field names are case sensitive.
- *
- * @param maintainType true if the type field should be included in deserialized objects
- */
- public static RuntimeTypeAdapterFactory of(Class baseType, String typeFieldName, boolean maintainType) {
- return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName, maintainType);
- }
-
- /**
- * Creates a new runtime type adapter using for {@code baseType} using {@code
- * typeFieldName} as the type field name. Type field names are case sensitive.
- */
- public static RuntimeTypeAdapterFactory of(Class baseType, String typeFieldName) {
- return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName, false);
- }
-
- /**
- * Creates a new runtime type adapter for {@code baseType} using {@code "type"} as
- * the type field name.
- */
- public static RuntimeTypeAdapterFactory of(Class baseType) {
- return new RuntimeTypeAdapterFactory<>(baseType, "type", false);
- }
-
- /**
- * Ensures that this factory will handle not just the given {@code baseType}, but any subtype
- * of that type.
- */
- public RuntimeTypeAdapterFactory recognizeSubtypes() {
- this.recognizeSubtypes = true;
- return this;
- }
-
- /**
- * Registers {@code type} identified by {@code label}. Labels are case
- * sensitive.
- *
- * @throws IllegalArgumentException if either {@code type} or {@code label}
- * have already been registered on this type adapter.
- */
- public RuntimeTypeAdapterFactory registerSubtype(Class extends T> type, String label) {
- if (type == null || label == null) {
- throw new NullPointerException();
- }
- if (subtypeToLabel.containsKey(type) || labelToSubtype.containsKey(label)) {
- throw new IllegalArgumentException("types and labels must be unique");
- }
- labelToSubtype.put(label, type);
- subtypeToLabel.put(type, label);
- return this;
- }
-
- /**
- * Registers {@code type} identified by its {@link Class#getSimpleName simple
- * name}. Labels are case sensitive.
- *
- * @throws IllegalArgumentException if either {@code type} or its simple name
- * have already been registered on this type adapter.
- */
- public RuntimeTypeAdapterFactory registerSubtype(Class extends T> type) {
- return registerSubtype(type, type.getSimpleName());
- }
-
- @Override
- public TypeAdapter create(Gson gson, TypeToken type) {
- if (type == null) {
- return null;
- }
- Class> rawType = type.getRawType();
- boolean handle =
- recognizeSubtypes ? baseType.isAssignableFrom(rawType) : baseType.equals(rawType);
- if (!handle) {
- return null;
- }
-
- final TypeAdapter jsonElementAdapter = gson.getAdapter(JsonElement.class);
- final Map> labelToDelegate = new LinkedHashMap<>();
- final Map, TypeAdapter>> subtypeToDelegate = new LinkedHashMap<>();
- for (Map.Entry> entry : labelToSubtype.entrySet()) {
- TypeAdapter> delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.getValue()));
- labelToDelegate.put(entry.getKey(), delegate);
- subtypeToDelegate.put(entry.getValue(), delegate);
- }
-
- return new TypeAdapter() {
- @Override public R read(JsonReader in) throws IOException {
- JsonElement jsonElement = jsonElementAdapter.read(in);
- JsonElement labelJsonElement;
- if (maintainType) {
- labelJsonElement = jsonElement.getAsJsonObject().get(typeFieldName);
- } else {
- labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName);
- }
-
- if (labelJsonElement == null) {
- throw new JsonParseException("cannot deserialize " + baseType
- + " because it does not define a field named " + typeFieldName);
- }
- String label = labelJsonElement.getAsString();
- @SuppressWarnings("unchecked") // registration requires that subtype extends T
- TypeAdapter delegate = (TypeAdapter) labelToDelegate.get(label);
- if (delegate == null) {
- throw new JsonParseException("cannot deserialize " + baseType + " subtype named "
- + label + "; did you forget to register a subtype?");
- }
- return delegate.fromJsonTree(jsonElement);
- }
-
- @Override public void write(JsonWriter out, R value) throws IOException {
- Class> srcType = value.getClass();
- String label = subtypeToLabel.get(srcType);
- @SuppressWarnings("unchecked") // registration requires that subtype extends T
- TypeAdapter delegate = (TypeAdapter) subtypeToDelegate.get(srcType);
- if (delegate == null) {
- throw new JsonParseException("cannot serialize " + srcType.getName()
- + "; did you forget to register a subtype?");
- }
- JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject();
-
- if (maintainType) {
- jsonElementAdapter.write(out, jsonObject);
- return;
- }
-
- JsonObject clone = new JsonObject();
-
- if (jsonObject.has(typeFieldName)) {
- throw new JsonParseException("cannot serialize " + srcType.getName()
- + " because it already defines a field named " + typeFieldName);
- }
- clone.add(typeFieldName, new JsonPrimitive(label));
-
- for (Map.Entry e : jsonObject.entrySet()) {
- clone.add(e.getKey(), e.getValue());
- }
- jsonElementAdapter.write(out, clone);
- }
- }.nullSafe();
- }
-}
diff --git a/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java b/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java
deleted file mode 100644
index 2278f842bf..0000000000
--- a/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * 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.google.gson.typeadapters;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
-import com.google.gson.JsonParseException;
-import com.google.gson.TypeAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-
-public final class UtcDateTypeAdapter extends TypeAdapter {
- private final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC");
-
- @Override
- public void write(JsonWriter out, Date date) throws IOException {
- if (date == null) {
- out.nullValue();
- } else {
- String value = format(date, true, UTC_TIME_ZONE);
- out.value(value);
- }
- }
-
- @Override
- public Date read(JsonReader in) throws IOException {
- try {
- switch (in.peek()) {
- case NULL:
- in.nextNull();
- return null;
- default:
- String date = in.nextString();
- // Instead of using iso8601Format.parse(value), we use Jackson's date parsing
- // This is because Android doesn't support XXX because it is JDK 1.6
- return parse(date, new ParsePosition(0));
- }
- } catch (ParseException e) {
- throw new JsonParseException(e);
- }
- }
-
- // Date parsing code from Jackson databind ISO8601Utils.java
- // https://github.com/FasterXML/jackson-databind/blob/master/src/main/java/com/fasterxml/jackson/databind/util/ISO8601Utils.java
- private static final String GMT_ID = "GMT";
-
- /**
- * Format date into yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm]
- *
- * @param date the date to format
- * @param millis true to include millis precision otherwise false
- * @param tz timezone to use for the formatting (GMT will produce 'Z')
- * @return the date formatted as yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm]
- */
- private static String format(Date date, boolean millis, TimeZone tz) {
- Calendar calendar = new GregorianCalendar(tz, Locale.US);
- calendar.setTime(date);
-
- // estimate capacity of buffer as close as we can (yeah, that's pedantic ;)
- int capacity = "yyyy-MM-ddThh:mm:ss".length();
- capacity += millis ? ".sss".length() : 0;
- capacity += tz.getRawOffset() == 0 ? "Z".length() : "+hh:mm".length();
- StringBuilder formatted = new StringBuilder(capacity);
-
- padInt(formatted, calendar.get(Calendar.YEAR), "yyyy".length());
- formatted.append('-');
- padInt(formatted, calendar.get(Calendar.MONTH) + 1, "MM".length());
- formatted.append('-');
- padInt(formatted, calendar.get(Calendar.DAY_OF_MONTH), "dd".length());
- formatted.append('T');
- padInt(formatted, calendar.get(Calendar.HOUR_OF_DAY), "hh".length());
- formatted.append(':');
- padInt(formatted, calendar.get(Calendar.MINUTE), "mm".length());
- formatted.append(':');
- padInt(formatted, calendar.get(Calendar.SECOND), "ss".length());
- if (millis) {
- formatted.append('.');
- padInt(formatted, calendar.get(Calendar.MILLISECOND), "sss".length());
- }
-
- int offset = tz.getOffset(calendar.getTimeInMillis());
- if (offset != 0) {
- int hours = Math.abs((offset / (60 * 1000)) / 60);
- int minutes = Math.abs((offset / (60 * 1000)) % 60);
- formatted.append(offset < 0 ? '-' : '+');
- padInt(formatted, hours, "hh".length());
- formatted.append(':');
- padInt(formatted, minutes, "mm".length());
- } else {
- formatted.append('Z');
- }
-
- return formatted.toString();
- }
- /**
- * Zero pad a number to a specified length
- *
- * @param buffer buffer to use for padding
- * @param value the integer value to pad if necessary.
- * @param length the length of the string we should zero pad
- */
- private static void padInt(StringBuilder buffer, int value, int length) {
- String strValue = Integer.toString(value);
- for (int i = length - strValue.length(); i > 0; i--) {
- buffer.append('0');
- }
- buffer.append(strValue);
- }
-
- /**
- * Parse a date from ISO-8601 formatted string. It expects a format
- * [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]]
- *
- * @param date ISO string to parse in the appropriate format.
- * @param pos The position to start parsing from, updated to where parsing stopped.
- * @return the parsed date
- * @throws ParseException if the date is not in the appropriate format
- */
- private static Date parse(String date, ParsePosition pos) throws ParseException {
- Exception fail = null;
- try {
- int offset = pos.getIndex();
-
- // extract year
- int year = parseInt(date, offset, offset += 4);
- if (checkOffset(date, offset, '-')) {
- offset += 1;
- }
-
- // extract month
- int month = parseInt(date, offset, offset += 2);
- if (checkOffset(date, offset, '-')) {
- offset += 1;
- }
-
- // extract day
- int day = parseInt(date, offset, offset += 2);
- // default time value
- int hour = 0;
- int minutes = 0;
- int seconds = 0;
- int milliseconds = 0; // always use 0 otherwise returned date will include millis of current time
- if (checkOffset(date, offset, 'T')) {
-
- // extract hours, minutes, seconds and milliseconds
- hour = parseInt(date, offset += 1, offset += 2);
- if (checkOffset(date, offset, ':')) {
- offset += 1;
- }
-
- minutes = parseInt(date, offset, offset += 2);
- if (checkOffset(date, offset, ':')) {
- offset += 1;
- }
- // second and milliseconds can be optional
- if (date.length() > offset) {
- char c = date.charAt(offset);
- if (c != 'Z' && c != '+' && c != '-') {
- seconds = parseInt(date, offset, offset += 2);
- // milliseconds can be optional in the format
- if (checkOffset(date, offset, '.')) {
- milliseconds = parseInt(date, offset += 1, offset += 3);
- }
- }
- }
- }
-
- // extract timezone
- String timezoneId;
- if (date.length() <= offset) {
- throw new IllegalArgumentException("No time zone indicator");
- }
- char timezoneIndicator = date.charAt(offset);
- if (timezoneIndicator == '+' || timezoneIndicator == '-') {
- String timezoneOffset = date.substring(offset);
- timezoneId = GMT_ID + timezoneOffset;
- offset += timezoneOffset.length();
- } else if (timezoneIndicator == 'Z') {
- timezoneId = GMT_ID;
- offset += 1;
- } else {
- throw new IndexOutOfBoundsException("Invalid time zone indicator " + timezoneIndicator);
- }
-
- TimeZone timezone = TimeZone.getTimeZone(timezoneId);
- if (!timezone.getID().equals(timezoneId)) {
- throw new IndexOutOfBoundsException();
- }
-
- Calendar calendar = new GregorianCalendar(timezone);
- calendar.setLenient(false);
- calendar.set(Calendar.YEAR, year);
- calendar.set(Calendar.MONTH, month - 1);
- calendar.set(Calendar.DAY_OF_MONTH, day);
- calendar.set(Calendar.HOUR_OF_DAY, hour);
- calendar.set(Calendar.MINUTE, minutes);
- calendar.set(Calendar.SECOND, seconds);
- calendar.set(Calendar.MILLISECOND, milliseconds);
-
- pos.setIndex(offset);
- return calendar.getTime();
- // If we get a ParseException it'll already have the right message/offset.
- // Other exception types can convert here.
- } catch (IndexOutOfBoundsException e) {
- fail = e;
- } catch (NumberFormatException e) {
- fail = e;
- } catch (IllegalArgumentException e) {
- fail = e;
- }
- String input = (date == null) ? null : ("'" + date + "'");
- throw new ParseException("Failed to parse date [" + input + "]: " + fail.getMessage(), pos.getIndex());
- }
-
- /**
- * Check if the expected character exist at the given offset in the value.
- *
- * @param value the string to check at the specified offset
- * @param offset the offset to look for the expected character
- * @param expected the expected character
- * @return true if the expected character exist at the given offset
- */
- private static boolean checkOffset(String value, int offset, char expected) {
- return (offset < value.length()) && (value.charAt(offset) == expected);
- }
-
- /**
- * Parse an integer located between 2 given offsets in a string
- *
- * @param value the string to parse
- * @param beginIndex the start index for the integer in the string
- * @param endIndex the end index for the integer in the string
- * @return the int
- * @throws NumberFormatException if the value is not a number
- */
- private static int parseInt(String value, int beginIndex, int endIndex) throws NumberFormatException {
- if (beginIndex < 0 || endIndex > value.length() || beginIndex > endIndex) {
- throw new NumberFormatException(value);
- }
- // use same logic as in Integer.parseInt() but less generic we're not supporting negative values
- int i = beginIndex;
- int result = 0;
- int digit;
- if (i < endIndex) {
- digit = Character.digit(value.charAt(i++), 10);
- if (digit < 0) {
- throw new NumberFormatException("Invalid number: " + value);
- }
- result = -digit;
- }
- while (i < endIndex) {
- digit = Character.digit(value.charAt(i++), 10);
- if (digit < 0) {
- throw new NumberFormatException("Invalid number: " + value);
- }
- result *= 10;
- result -= digit;
- }
- return -result;
- }
-}
diff --git a/extras/src/test/java/com/google/gson/graph/GraphAdapterBuilderTest.java b/extras/src/test/java/com/google/gson/graph/GraphAdapterBuilderTest.java
deleted file mode 100644
index 3b2425ec9e..0000000000
--- a/extras/src/test/java/com/google/gson/graph/GraphAdapterBuilderTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * 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.google.gson.graph;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-public final class GraphAdapterBuilderTest {
- @Test
- public void testSerialization() {
- Roshambo rock = new Roshambo("ROCK");
- Roshambo scissors = new Roshambo("SCISSORS");
- Roshambo paper = new Roshambo("PAPER");
- rock.beats = scissors;
- scissors.beats = paper;
- paper.beats = rock;
-
- GsonBuilder gsonBuilder = new GsonBuilder();
- new GraphAdapterBuilder()
- .addType(Roshambo.class)
- .registerOn(gsonBuilder);
- Gson gson = gsonBuilder.create();
-
- assertEquals("{'0x1':{'name':'ROCK','beats':'0x2'}," +
- "'0x2':{'name':'SCISSORS','beats':'0x3'}," +
- "'0x3':{'name':'PAPER','beats':'0x1'}}",
- gson.toJson(rock).replace('"', '\''));
- }
-
- @Test
- public void testDeserialization() {
- String json = "{'0x1':{'name':'ROCK','beats':'0x2'}," +
- "'0x2':{'name':'SCISSORS','beats':'0x3'}," +
- "'0x3':{'name':'PAPER','beats':'0x1'}}";
-
- GsonBuilder gsonBuilder = new GsonBuilder();
- new GraphAdapterBuilder()
- .addType(Roshambo.class)
- .registerOn(gsonBuilder);
- Gson gson = gsonBuilder.create();
-
- Roshambo rock = gson.fromJson(json, Roshambo.class);
- assertEquals("ROCK", rock.name);
- Roshambo scissors = rock.beats;
- assertEquals("SCISSORS", scissors.name);
- Roshambo paper = scissors.beats;
- assertEquals("PAPER", paper.name);
- assertSame(rock, paper.beats);
- }
-
- @Test
- public void testDeserializationDirectSelfReference() {
- String json = "{'0x1':{'name':'SUICIDE','beats':'0x1'}}";
-
- GsonBuilder gsonBuilder = new GsonBuilder();
- new GraphAdapterBuilder()
- .addType(Roshambo.class)
- .registerOn(gsonBuilder);
- Gson gson = gsonBuilder.create();
-
- Roshambo suicide = gson.fromJson(json, Roshambo.class);
- assertEquals("SUICIDE", suicide.name);
- assertSame(suicide, suicide.beats);
- }
-
- @Test
- public void testSerializeListOfLists() {
- Type listOfListsType = new TypeToken>>() {}.getType();
- Type listOfAnyType = new TypeToken>() {}.getType();
-
- List> listOfLists = new ArrayList<>();
- listOfLists.add(listOfLists);
- listOfLists.add(new ArrayList<>());
-
- GsonBuilder gsonBuilder = new GsonBuilder();
- new GraphAdapterBuilder()
- .addType(listOfListsType)
- .addType(listOfAnyType)
- .registerOn(gsonBuilder);
- Gson gson = gsonBuilder.create();
-
- String json = gson.toJson(listOfLists, listOfListsType);
- assertEquals("{'0x1':['0x1','0x2'],'0x2':[]}", json.replace('"', '\''));
- }
-
- @Test
- public void testDeserializeListOfLists() {
- Type listOfAnyType = new TypeToken>() {}.getType();
- Type listOfListsType = new TypeToken>>() {}.getType();
-
- GsonBuilder gsonBuilder = new GsonBuilder();
- new GraphAdapterBuilder()
- .addType(listOfListsType)
- .addType(listOfAnyType)
- .registerOn(gsonBuilder);
- Gson gson = gsonBuilder.create();
-
- List> listOfLists = gson.fromJson("{'0x1':['0x1','0x2'],'0x2':[]}", listOfListsType);
- assertEquals(2, listOfLists.size());
- assertSame(listOfLists, listOfLists.get(0));
- assertEquals(Collections.emptyList(), listOfLists.get(1));
- }
-
- @Test
- public void testSerializationWithMultipleTypes() {
- Company google = new Company("Google");
- new Employee("Jesse", google);
- new Employee("Joel", google);
-
- GsonBuilder gsonBuilder = new GsonBuilder();
- new GraphAdapterBuilder()
- .addType(Company.class)
- .addType(Employee.class)
- .registerOn(gsonBuilder);
- Gson gson = gsonBuilder.create();
-
- assertEquals("{'0x1':{'name':'Google','employees':['0x2','0x3']},"
- + "'0x2':{'name':'Jesse','company':'0x1'},"
- + "'0x3':{'name':'Joel','company':'0x1'}}",
- gson.toJson(google).replace('"', '\''));
- }
-
- @Test
- public void testDeserializationWithMultipleTypes() {
- GsonBuilder gsonBuilder = new GsonBuilder();
- new GraphAdapterBuilder()
- .addType(Company.class)
- .addType(Employee.class)
- .registerOn(gsonBuilder);
- Gson gson = gsonBuilder.create();
-
- String json = "{'0x1':{'name':'Google','employees':['0x2','0x3']},"
- + "'0x2':{'name':'Jesse','company':'0x1'},"
- + "'0x3':{'name':'Joel','company':'0x1'}}";
- Company company = gson.fromJson(json, Company.class);
- assertEquals("Google", company.name);
- Employee jesse = company.employees.get(0);
- assertEquals("Jesse", jesse.name);
- assertEquals(company, jesse.company);
- Employee joel = company.employees.get(1);
- assertEquals("Joel", joel.name);
- assertEquals(company, joel.company);
- }
-
- static class Roshambo {
- String name;
- Roshambo beats;
- Roshambo(String name) {
- this.name = name;
- }
- }
-
- static class Employee {
- final String name;
- final Company company;
- Employee(String name, Company company) {
- this.name = name;
- this.company = company;
- this.company.employees.add(this);
- }
- }
-
- static class Company {
- final String name;
- final List employees = new ArrayList<>();
- Company(String name) {
- this.name = name;
- }
- }
-}
diff --git a/extras/src/test/java/com/google/gson/interceptors/InterceptorTest.java b/extras/src/test/java/com/google/gson/interceptors/InterceptorTest.java
deleted file mode 100644
index ee475c8e2f..0000000000
--- a/extras/src/test/java/com/google/gson/interceptors/InterceptorTest.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc.
- *
- * 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.google.gson.interceptors;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonSyntaxException;
-import com.google.gson.TypeAdapter;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-import java.io.IOException;
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Unit tests for {@link Intercept} and {@link JsonPostDeserializer}.
- *
- * @author Inderjeet Singh
- */
-public final class InterceptorTest {
-
- private Gson gson;
-
- @Before
- public void setUp() throws Exception {
- this.gson = new GsonBuilder()
- .registerTypeAdapterFactory(new InterceptorFactory())
- .enableComplexMapKeySerialization()
- .create();
- }
-
- @Test
- public void testExceptionsPropagated() {
- try {
- gson.fromJson("{}", User.class);
- fail();
- } catch (JsonParseException expected) {}
- }
-
- @Test
- public void testTopLevelClass() {
- User user = gson.fromJson("{name:'bob',password:'pwd'}", User.class);
- assertEquals(User.DEFAULT_EMAIL, user.email);
- }
-
- @Test
- public void testList() {
- List list = gson.fromJson("[{name:'bob',password:'pwd'}]", new TypeToken>(){}.getType());
- User user = list.get(0);
- assertEquals(User.DEFAULT_EMAIL, user.email);
- }
-
- @Test
- public void testCollection() {
- Collection list = gson.fromJson("[{name:'bob',password:'pwd'}]", new TypeToken>(){}.getType());
- User user = list.iterator().next();
- assertEquals(User.DEFAULT_EMAIL, user.email);
- }
-
- @Test
- public void testMapKeyAndValues() {
- Type mapType = new TypeToken>(){}.getType();
- try {
- gson.fromJson("[[{name:'bob',password:'pwd'},{}]]", mapType);
- fail();
- } catch (JsonSyntaxException expected) {}
- Map map = gson.fromJson("[[{name:'bob',password:'pwd'},{city:'Mountain View',state:'CA',zip:'94043'}]]",
- mapType);
- Entry entry = map.entrySet().iterator().next();
- assertEquals(User.DEFAULT_EMAIL, entry.getKey().email);
- assertEquals(Address.DEFAULT_FIRST_LINE, entry.getValue().firstLine);
- }
-
- @Test
- public void testField() {
- UserGroup userGroup = gson.fromJson("{user:{name:'bob',password:'pwd'}}", UserGroup.class);
- assertEquals(User.DEFAULT_EMAIL, userGroup.user.email);
- }
-
- @Test
- public void testCustomTypeAdapter() {
- Gson gson = new GsonBuilder()
- .registerTypeAdapter(User.class, new TypeAdapter() {
- @Override public void write(JsonWriter out, User value) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- @Override public User read(JsonReader in) throws IOException {
- in.beginObject();
- in.nextName();
- String name = in.nextString();
- in.nextName();
- String password = in.nextString();
- in.endObject();
- return new User(name, password);
- }
- })
- .registerTypeAdapterFactory(new InterceptorFactory())
- .create();
- UserGroup userGroup = gson.fromJson("{user:{name:'bob',password:'pwd'}}", UserGroup.class);
- assertEquals(User.DEFAULT_EMAIL, userGroup.user.email);
- }
-
- @Test
- public void testDirectInvocationOfTypeAdapter() throws Exception {
- TypeAdapter adapter = gson.getAdapter(UserGroup.class);
- UserGroup userGroup = adapter.fromJson("{\"user\":{\"name\":\"bob\",\"password\":\"pwd\"}}");
- assertEquals(User.DEFAULT_EMAIL, userGroup.user.email);
- }
-
- @SuppressWarnings("unused")
- private static final class UserGroup {
- User user;
- String city;
- }
-
- @Intercept(postDeserialize = UserValidator.class)
- @SuppressWarnings("unused")
- private static final class User {
- static final String DEFAULT_EMAIL = "invalid@invalid.com";
- String name;
- String password;
- String email;
- Address address;
- public User(String name, String password) {
- this.name = name;
- this.password = password;
- }
- }
-
- public static final class UserValidator implements JsonPostDeserializer {
- @Override public void postDeserialize(User user) {
- if (user.name == null || user.password == null) {
- throw new JsonSyntaxException("name and password are required fields.");
- }
- if (user.email == null) user.email = User.DEFAULT_EMAIL;
- }
- }
-
- @Intercept(postDeserialize = AddressValidator.class)
- @SuppressWarnings("unused")
- private static final class Address {
- static final String DEFAULT_FIRST_LINE = "unknown";
- String firstLine;
- String secondLine;
- String city;
- String state;
- String zip;
- }
-
- public static final class AddressValidator implements JsonPostDeserializer {
- @Override public void postDeserialize(Address address) {
- if (address.city == null || address.state == null || address.zip == null) {
- throw new JsonSyntaxException("Address city, state and zip are required fields.");
- }
- if (address.firstLine == null) address.firstLine = Address.DEFAULT_FIRST_LINE;
- }
- }
-}
diff --git a/extras/src/test/java/com/google/gson/typeadapters/PostConstructAdapterFactoryTest.java b/extras/src/test/java/com/google/gson/typeadapters/PostConstructAdapterFactoryTest.java
deleted file mode 100644
index 65053bacbf..0000000000
--- a/extras/src/test/java/com/google/gson/typeadapters/PostConstructAdapterFactoryTest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2016 Gson Authors
- *
- * 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.google.gson.typeadapters;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import java.util.Arrays;
-import java.util.List;
-import javax.annotation.PostConstruct;
-import org.junit.Test;
-
-public class PostConstructAdapterFactoryTest {
- @Test
- public void test() throws Exception {
- Gson gson = new GsonBuilder()
- .registerTypeAdapterFactory(new PostConstructAdapterFactory())
- .create();
- gson.fromJson("{\"bread\": \"white\", \"cheese\": \"cheddar\"}", Sandwich.class);
- try {
- gson.fromJson("{\"bread\": \"cheesey bread\", \"cheese\": \"swiss\"}", Sandwich.class);
- fail();
- } catch (IllegalArgumentException expected) {
- assertEquals("too cheesey", expected.getMessage());
- }
- }
-
- @Test
- public void testList() {
- MultipleSandwiches sandwiches = new MultipleSandwiches(Arrays.asList(
- new Sandwich("white", "cheddar"),
- new Sandwich("whole wheat", "swiss")));
-
- Gson gson = new GsonBuilder().registerTypeAdapterFactory(new PostConstructAdapterFactory()).create();
-
- // Throws NullPointerException without the fix in https://github.com/google/gson/pull/1103
- String json = gson.toJson(sandwiches);
- assertEquals("{\"sandwiches\":[{\"bread\":\"white\",\"cheese\":\"cheddar\"},{\"bread\":\"whole wheat\",\"cheese\":\"swiss\"}]}", json);
-
- MultipleSandwiches sandwichesFromJson = gson.fromJson(json, MultipleSandwiches.class);
- assertEquals(sandwiches, sandwichesFromJson);
- }
-
- @SuppressWarnings("overrides") // for missing hashCode() override
- static class Sandwich {
- public String bread;
- public String cheese;
-
- public Sandwich(String bread, String cheese) {
- this.bread = bread;
- this.cheese = cheese;
- }
-
- @PostConstruct private void validate() {
- if (bread.equals("cheesey bread") && cheese != null) {
- throw new IllegalArgumentException("too cheesey");
- }
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == this) {
- return true;
- }
- if (!(o instanceof Sandwich)) {
- return false;
- }
- final Sandwich other = (Sandwich) o;
- if (this.bread == null ? other.bread != null : !this.bread.equals(other.bread)) {
- return false;
- }
- if (this.cheese == null ? other.cheese != null : !this.cheese.equals(other.cheese)) {
- return false;
- }
- return true;
- }
- }
-
- @SuppressWarnings("overrides") // for missing hashCode() override
- static class MultipleSandwiches {
- public List sandwiches;
-
- public MultipleSandwiches(List sandwiches) {
- this.sandwiches = sandwiches;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == this) {
- return true;
- }
- if (!(o instanceof MultipleSandwiches)) {
- return false;
- }
- final MultipleSandwiches other = (MultipleSandwiches) o;
- if (this.sandwiches == null ? other.sandwiches != null : !this.sandwiches.equals(other.sandwiches)) {
- return false;
- }
- return true;
- }
- }
-}
diff --git a/extras/src/test/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactoryTest.java b/extras/src/test/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactoryTest.java
deleted file mode 100644
index 1221b47bcc..0000000000
--- a/extras/src/test/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactoryTest.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * 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.google.gson.typeadapters;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonParseException;
-import com.google.gson.TypeAdapterFactory;
-import org.junit.Test;
-
-public final class RuntimeTypeAdapterFactoryTest {
-
- @Test
- public void testRuntimeTypeAdapter() {
- RuntimeTypeAdapterFactory rta = RuntimeTypeAdapterFactory.of(
- BillingInstrument.class)
- .registerSubtype(CreditCard.class);
- Gson gson = new GsonBuilder()
- .registerTypeAdapterFactory(rta)
- .create();
-
- CreditCard original = new CreditCard("Jesse", 234);
- assertEquals("{\"type\":\"CreditCard\",\"cvv\":234,\"ownerName\":\"Jesse\"}",
- gson.toJson(original, BillingInstrument.class));
- BillingInstrument deserialized = gson.fromJson(
- "{type:'CreditCard',cvv:234,ownerName:'Jesse'}", BillingInstrument.class);
- assertEquals("Jesse", deserialized.ownerName);
- assertTrue(deserialized instanceof CreditCard);
- }
-
- @Test
- public void testRuntimeTypeAdapterRecognizeSubtypes() {
- // We don't have an explicit factory for CreditCard.class, but we do have one for
- // BillingInstrument.class that has recognizeSubtypes(). So it should recognize CreditCard, and
- // when we call gson.toJson(original) below, without an explicit type, it should be invoked.
- RuntimeTypeAdapterFactory rta = RuntimeTypeAdapterFactory.of(
- BillingInstrument.class)
- .recognizeSubtypes()
- .registerSubtype(CreditCard.class);
- Gson gson = new GsonBuilder()
- .registerTypeAdapterFactory(rta)
- .create();
-
- CreditCard original = new CreditCard("Jesse", 234);
- assertEquals("{\"type\":\"CreditCard\",\"cvv\":234,\"ownerName\":\"Jesse\"}",
- gson.toJson(original));
- BillingInstrument deserialized = gson.fromJson(
- "{type:'CreditCard',cvv:234,ownerName:'Jesse'}", BillingInstrument.class);
- assertEquals("Jesse", deserialized.ownerName);
- assertTrue(deserialized instanceof CreditCard);
- }
-
- @Test
- public void testRuntimeTypeIsBaseType() {
- TypeAdapterFactory rta = RuntimeTypeAdapterFactory.of(
- BillingInstrument.class)
- .registerSubtype(BillingInstrument.class);
- Gson gson = new GsonBuilder()
- .registerTypeAdapterFactory(rta)
- .create();
-
- BillingInstrument original = new BillingInstrument("Jesse");
- assertEquals("{\"type\":\"BillingInstrument\",\"ownerName\":\"Jesse\"}",
- gson.toJson(original, BillingInstrument.class));
- BillingInstrument deserialized = gson.fromJson(
- "{type:'BillingInstrument',ownerName:'Jesse'}", BillingInstrument.class);
- assertEquals("Jesse", deserialized.ownerName);
- }
-
- @Test
- public void testNullBaseType() {
- try {
- RuntimeTypeAdapterFactory.of(null);
- fail();
- } catch (NullPointerException expected) {
- }
- }
-
- @Test
- public void testNullTypeFieldName() {
- try {
- RuntimeTypeAdapterFactory.of(BillingInstrument.class, null);
- fail();
- } catch (NullPointerException expected) {
- }
- }
-
- @Test
- public void testNullSubtype() {
- RuntimeTypeAdapterFactory rta = RuntimeTypeAdapterFactory.of(
- BillingInstrument.class);
- try {
- rta.registerSubtype(null);
- fail();
- } catch (NullPointerException expected) {
- }
- }
-
- @Test
- public void testNullLabel() {
- RuntimeTypeAdapterFactory rta = RuntimeTypeAdapterFactory.of(
- BillingInstrument.class);
- try {
- rta.registerSubtype(CreditCard.class, null);
- fail();
- } catch (NullPointerException expected) {
- }
- }
-
- @Test
- public void testDuplicateSubtype() {
- RuntimeTypeAdapterFactory rta = RuntimeTypeAdapterFactory.of(
- BillingInstrument.class);
- rta.registerSubtype(CreditCard.class, "CC");
- try {
- rta.registerSubtype(CreditCard.class, "Visa");
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
-
- @Test
- public void testDuplicateLabel() {
- RuntimeTypeAdapterFactory rta = RuntimeTypeAdapterFactory.of(
- BillingInstrument.class);
- rta.registerSubtype(CreditCard.class, "CC");
- try {
- rta.registerSubtype(BankTransfer.class, "CC");
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
-
- @Test
- public void testDeserializeMissingTypeField() {
- TypeAdapterFactory billingAdapter = RuntimeTypeAdapterFactory.of(BillingInstrument.class)
- .registerSubtype(CreditCard.class);
- Gson gson = new GsonBuilder()
- .registerTypeAdapterFactory(billingAdapter)
- .create();
- try {
- gson.fromJson("{ownerName:'Jesse'}", BillingInstrument.class);
- fail();
- } catch (JsonParseException expected) {
- }
- }
-
- @Test
- public void testDeserializeMissingSubtype() {
- TypeAdapterFactory billingAdapter = RuntimeTypeAdapterFactory.of(BillingInstrument.class)
- .registerSubtype(BankTransfer.class);
- Gson gson = new GsonBuilder()
- .registerTypeAdapterFactory(billingAdapter)
- .create();
- try {
- gson.fromJson("{type:'CreditCard',ownerName:'Jesse'}", BillingInstrument.class);
- fail();
- } catch (JsonParseException expected) {
- }
- }
-
- @Test
- public void testSerializeMissingSubtype() {
- TypeAdapterFactory billingAdapter = RuntimeTypeAdapterFactory.of(BillingInstrument.class)
- .registerSubtype(BankTransfer.class);
- Gson gson = new GsonBuilder()
- .registerTypeAdapterFactory(billingAdapter)
- .create();
- try {
- gson.toJson(new CreditCard("Jesse", 456), BillingInstrument.class);
- fail();
- } catch (JsonParseException expected) {
- }
- }
-
- @Test
- public void testSerializeCollidingTypeFieldName() {
- TypeAdapterFactory billingAdapter = RuntimeTypeAdapterFactory.of(BillingInstrument.class, "cvv")
- .registerSubtype(CreditCard.class);
- Gson gson = new GsonBuilder()
- .registerTypeAdapterFactory(billingAdapter)
- .create();
- try {
- gson.toJson(new CreditCard("Jesse", 456), BillingInstrument.class);
- fail();
- } catch (JsonParseException expected) {
- }
- }
-
- @Test
- public void testSerializeWrappedNullValue() {
- TypeAdapterFactory billingAdapter = RuntimeTypeAdapterFactory.of(BillingInstrument.class)
- .registerSubtype(CreditCard.class)
- .registerSubtype(BankTransfer.class);
- Gson gson = new GsonBuilder()
- .registerTypeAdapterFactory(billingAdapter)
- .create();
- String serialized = gson.toJson(new BillingInstrumentWrapper(null), BillingInstrumentWrapper.class);
- BillingInstrumentWrapper deserialized = gson.fromJson(serialized, BillingInstrumentWrapper.class);
- assertNull(deserialized.instrument);
- }
-
- static class BillingInstrumentWrapper {
- BillingInstrument instrument;
- BillingInstrumentWrapper(BillingInstrument instrument) {
- this.instrument = instrument;
- }
- }
-
- static class BillingInstrument {
- private final String ownerName;
- BillingInstrument(String ownerName) {
- this.ownerName = ownerName;
- }
- }
-
- static class CreditCard extends BillingInstrument {
- int cvv;
- CreditCard(String ownerName, int cvv) {
- super(ownerName);
- this.cvv = cvv;
- }
- }
-
- static class BankTransfer extends BillingInstrument {
- int bankAccount;
- BankTransfer(String ownerName, int bankAccount) {
- super(ownerName);
- this.bankAccount = bankAccount;
- }
- }
-}
diff --git a/extras/src/test/java/com/google/gson/typeadapters/UtcDateTypeAdapterTest.java b/extras/src/test/java/com/google/gson/typeadapters/UtcDateTypeAdapterTest.java
deleted file mode 100644
index b520183528..0000000000
--- a/extras/src/test/java/com/google/gson/typeadapters/UtcDateTypeAdapterTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * 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.google.gson.typeadapters;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonParseException;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-import org.junit.Test;
-
-public final class UtcDateTypeAdapterTest {
- private final Gson gson = new GsonBuilder()
- .registerTypeAdapter(Date.class, new UtcDateTypeAdapter())
- .create();
-
- @Test
- public void testLocalTimeZone() {
- Date expected = new Date();
- String json = gson.toJson(expected);
- Date actual = gson.fromJson(json, Date.class);
- assertEquals(expected.getTime(), actual.getTime());
- }
-
- @Test
- public void testDifferentTimeZones() {
- for (String timeZone : TimeZone.getAvailableIDs()) {
- Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
- Date expected = cal.getTime();
- String json = gson.toJson(expected);
- // System.out.println(json + ": " + timeZone);
- Date actual = gson.fromJson(json, Date.class);
- assertEquals(expected.getTime(), actual.getTime());
- }
- }
-
- /**
- * JDK 1.7 introduced support for XXX format to indicate UTC date. But Android is older JDK.
- * We want to make sure that this date is parseable in Android.
- */
- @Test
- public void testUtcDatesOnJdkBefore1_7() {
- Gson gson = new GsonBuilder()
- .registerTypeAdapter(Date.class, new UtcDateTypeAdapter())
- .create();
- gson.fromJson("'2014-12-05T04:00:00.000Z'", Date.class);
- }
-
- @Test
- public void testUtcWithJdk7Default() {
- Date expected = new Date();
- SimpleDateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.US);
- iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
- String expectedJson = "\"" + iso8601Format.format(expected) + "\"";
- String actualJson = gson.toJson(expected);
- assertEquals(expectedJson, actualJson);
- Date actual = gson.fromJson(expectedJson, Date.class);
- assertEquals(expected.getTime(), actual.getTime());
- }
-
- @Test
- public void testNullDateSerialization() {
- String json = gson.toJson(null, Date.class);
- assertEquals("null", json);
- }
-
- @Test
- public void testWellFormedParseException() {
- try {
- gson.fromJson("2017-06-20T14:32:30", Date.class);
- fail("No exception");
- } catch (JsonParseException exe) {
- assertEquals("java.text.ParseException: Failed to parse date ['2017-06-20T14']: 2017-06-20T14", exe.getMessage());
- }
- }
-}
diff --git a/gson/pom.xml b/gson/pom.xml
index d66e1dcb58..b4b7192c41 100644
--- a/gson/pom.xml
+++ b/gson/pom.xml
@@ -2,9 +2,9 @@
4.0.0
- com.google.code.gson
+ com.firework.gson
gson-parent
- 2.10.1
+ 2.10.1.0
gson
@@ -123,12 +123,12 @@
- ${project.build.directory}/test-classes/com/google/gson/functional/EnumWithObfuscatedTest.class
- ${project.build.directory}/test-classes-obfuscated-injar/com/google/gson/functional/EnumWithObfuscatedTest.class
+ ${project.build.directory}/test-classes/com/firework/gson/functional/EnumWithObfuscatedTest.class
+ ${project.build.directory}/test-classes-obfuscated-injar/com/firework/gson/functional/EnumWithObfuscatedTest.class
- ${project.build.directory}/test-classes/com/google/gson/functional/EnumWithObfuscatedTest$Gender.class
- ${project.build.directory}/test-classes-obfuscated-injar/com/google/gson/functional/EnumWithObfuscatedTest$Gender.class
+ ${project.build.directory}/test-classes/com/firework/gson/functional/EnumWithObfuscatedTest$Gender.class
+ ${project.build.directory}/test-classes-obfuscated-injar/com/firework/gson/functional/EnumWithObfuscatedTest$Gender.class
@@ -171,10 +171,10 @@
copy-resources
- ${project.build.directory}/test-classes/com/google/gson/functional
+ ${project.build.directory}/test-classes/com/firework/gson/functional
- ${project.build.directory}/test-classes-obfuscated-outjar/com/google/gson/functional
+ ${project.build.directory}/test-classes-obfuscated-outjar/com/firework/gson/functional
EnumWithObfuscatedTest.class
EnumWithObfuscatedTest$Gender.class
@@ -233,7 +233,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- com.google.gson.internal:com.google.gson.internal.bind
+ com.firework.gson.internal:com.firework.gson.internal.bind
diff --git a/metrics/README.md b/metrics/README.md
deleted file mode 100644
index 8c95485de2..0000000000
--- a/metrics/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# metrics
-
-This Maven module contains the source code for running internal benchmark tests against Gson.
diff --git a/metrics/pom.xml b/metrics/pom.xml
deleted file mode 100644
index 7a9dc18ee0..0000000000
--- a/metrics/pom.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-
- 4.0.0
-
- com.google.code.gson
- gson-parent
- 2.10.1
-
-
- gson-metrics
- 2011
- Gson Metrics
- Performance Metrics for Google Gson library
-
-
-
- Apache-2.0
- https://www.apache.org/licenses/LICENSE-2.0.txt
-
-
-
-
- Google, Inc.
- https://www.google.com
-
-
-
-
- com.google.code.gson
- gson
- ${project.parent.version}
-
-
- com.fasterxml.jackson.core
- jackson-databind
- 2.14.1
-
-
- com.google.caliper
- caliper
- 1.0-beta-3
-
-
-
-
-
-
-
- com.github.siom79.japicmp
- japicmp-maven-plugin
- 0.17.1
-
-
- true
-
-
-
- org.apache.maven.plugins
- maven-deploy-plugin
-
-
- true
-
-
-
-
-
-
-
-
- Inderjeet Singh
- Google Inc.
-
-
- Joel Leitch
- Google Inc.
-
-
- Jesse Wilson
- Google Inc.
-
-
-
diff --git a/metrics/src/main/java/com/google/gson/metrics/BagOfPrimitives.java b/metrics/src/main/java/com/google/gson/metrics/BagOfPrimitives.java
deleted file mode 100644
index a073974d4f..0000000000
--- a/metrics/src/main/java/com/google/gson/metrics/BagOfPrimitives.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * 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.google.gson.metrics;
-
-/**
- * Class with a bunch of primitive fields
- *
- * @author Inderjeet Singh
- */
-public class BagOfPrimitives {
- public static final long DEFAULT_VALUE = 0;
- public long longValue;
- public int intValue;
- public boolean booleanValue;
- public String stringValue;
-
- public BagOfPrimitives() {
- this(DEFAULT_VALUE, 0, false, "");
- }
-
- public BagOfPrimitives(long longValue, int intValue, boolean booleanValue, String stringValue) {
- this.longValue = longValue;
- this.intValue = intValue;
- this.booleanValue = booleanValue;
- this.stringValue = stringValue;
- }
-
- public int getIntValue() {
- return intValue;
- }
-
- public String getExpectedJson() {
- return "{"
- + "\"longValue\":" + longValue + ","
- + "\"intValue\":" + intValue + ","
- + "\"booleanValue\":" + booleanValue + ","
- + "\"stringValue\":\"" + stringValue + "\""
- + "}";
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + (booleanValue ? 1231 : 1237);
- result = prime * result + intValue;
- result = prime * result + (int) (longValue ^ (longValue >>> 32));
- result = prime * result + ((stringValue == null) ? 0 : stringValue.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (getClass() != obj.getClass()) return false;
- BagOfPrimitives other = (BagOfPrimitives) obj;
- if (booleanValue != other.booleanValue) return false;
- if (intValue != other.intValue) return false;
- if (longValue != other.longValue) return false;
- if (stringValue == null) {
- return other.stringValue == null;
- } else {
- return stringValue.equals(other.stringValue);
- }
- }
-
- @Override
- public String toString() {
- return String.format("(longValue=%d,intValue=%d,booleanValue=%b,stringValue=%s)",
- longValue, intValue, booleanValue, stringValue);
- }
-}
diff --git a/metrics/src/main/java/com/google/gson/metrics/BagOfPrimitivesDeserializationBenchmark.java b/metrics/src/main/java/com/google/gson/metrics/BagOfPrimitivesDeserializationBenchmark.java
deleted file mode 100644
index 80881dc8e6..0000000000
--- a/metrics/src/main/java/com/google/gson/metrics/BagOfPrimitivesDeserializationBenchmark.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * 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.google.gson.metrics;
-
-import com.google.caliper.BeforeExperiment;
-import com.google.gson.Gson;
-import com.google.gson.stream.JsonReader;
-import java.io.IOException;
-import java.io.StringReader;
-import java.lang.reflect.Field;
-
-/**
- * Caliper based micro benchmarks for Gson
- *
- * @author Inderjeet Singh
- * @author Jesse Wilson
- * @author Joel Leitch
- */
-public class BagOfPrimitivesDeserializationBenchmark {
-
- private Gson gson;
- private String json;
-
- public static void main(String[] args) {
- NonUploadingCaliperRunner.run(BagOfPrimitivesDeserializationBenchmark.class, args);
- }
-
- @BeforeExperiment
- void setUp() throws Exception {
- this.gson = new Gson();
- BagOfPrimitives bag = new BagOfPrimitives(10L, 1, false, "foo");
- this.json = gson.toJson(bag);
- }
-
- /**
- * Benchmark to measure Gson performance for deserializing an object
- */
- public void timeBagOfPrimitivesDefault(int reps) {
- for (int i=0; i fieldType = field.getType();
- if (fieldType.equals(long.class)) {
- field.setLong(bag, jr.nextLong());
- } else if (fieldType.equals(int.class)) {
- field.setInt(bag, jr.nextInt());
- } else if (fieldType.equals(boolean.class)) {
- field.setBoolean(bag, jr.nextBoolean());
- } else if (fieldType.equals(String.class)) {
- field.set(bag, jr.nextString());
- } else {
- throw new RuntimeException("Unexpected: type: " + fieldType + ", name: " + name);
- }
- }
- }
- }
- jr.endObject();
- }
- }
-}
diff --git a/metrics/src/main/java/com/google/gson/metrics/CollectionsDeserializationBenchmark.java b/metrics/src/main/java/com/google/gson/metrics/CollectionsDeserializationBenchmark.java
deleted file mode 100644
index 738b5ae4bf..0000000000
--- a/metrics/src/main/java/com/google/gson/metrics/CollectionsDeserializationBenchmark.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * 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.google.gson.metrics;
-
-import com.google.caliper.BeforeExperiment;
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import java.io.IOException;
-import java.io.StringReader;
-import java.lang.reflect.Field;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Caliper based micro benchmarks for Gson
- *
- * @author Inderjeet Singh
- */
-public class CollectionsDeserializationBenchmark {
-
- private static final TypeToken> LIST_TYPE_TOKEN = new TypeToken>(){};
- private static final Type LIST_TYPE = LIST_TYPE_TOKEN.getType();
- private Gson gson;
- private String json;
-
- public static void main(String[] args) {
- NonUploadingCaliperRunner.run(CollectionsDeserializationBenchmark.class, args);
- }
-
- @BeforeExperiment
- void setUp() throws Exception {
- this.gson = new Gson();
- List bags = new ArrayList<>();
- for (int i = 0; i < 100; ++i) {
- bags.add(new BagOfPrimitives(10L, 1, false, "foo"));
- }
- this.json = gson.toJson(bags, LIST_TYPE);
- }
-
- /**
- * Benchmark to measure Gson performance for deserializing an object
- */
- public void timeCollectionsDefault(int reps) {
- for (int i=0; i bags = new ArrayList<>();
- while(jr.hasNext()) {
- jr.beginObject();
- long longValue = 0;
- int intValue = 0;
- boolean booleanValue = false;
- String stringValue = null;
- while(jr.hasNext()) {
- String name = jr.nextName();
- if (name.equals("longValue")) {
- longValue = jr.nextLong();
- } else if (name.equals("intValue")) {
- intValue = jr.nextInt();
- } else if (name.equals("booleanValue")) {
- booleanValue = jr.nextBoolean();
- } else if (name.equals("stringValue")) {
- stringValue = jr.nextString();
- } else {
- throw new IOException("Unexpected name: " + name);
- }
- }
- jr.endObject();
- bags.add(new BagOfPrimitives(longValue, intValue, booleanValue, stringValue));
- }
- jr.endArray();
- }
- }
-
- /**
- * This benchmark measures the ideal Gson performance: the cost of parsing a JSON stream and
- * setting object values by reflection. We should strive to reduce the discrepancy between this
- * and {@link #timeCollectionsDefault(int)} .
- */
- public void timeCollectionsReflectionStreaming(int reps) throws Exception {
- for (int i=0; i bags = new ArrayList<>();
- while(jr.hasNext()) {
- jr.beginObject();
- BagOfPrimitives bag = new BagOfPrimitives();
- while(jr.hasNext()) {
- String name = jr.nextName();
- for (Field field : BagOfPrimitives.class.getDeclaredFields()) {
- if (field.getName().equals(name)) {
- Class> fieldType = field.getType();
- if (fieldType.equals(long.class)) {
- field.setLong(bag, jr.nextLong());
- } else if (fieldType.equals(int.class)) {
- field.setInt(bag, jr.nextInt());
- } else if (fieldType.equals(boolean.class)) {
- field.setBoolean(bag, jr.nextBoolean());
- } else if (fieldType.equals(String.class)) {
- field.set(bag, jr.nextString());
- } else {
- throw new RuntimeException("Unexpected: type: " + fieldType + ", name: " + name);
- }
- }
- }
- }
- jr.endObject();
- bags.add(bag);
- }
- jr.endArray();
- }
- }
-}
diff --git a/metrics/src/main/java/com/google/gson/metrics/NonUploadingCaliperRunner.java b/metrics/src/main/java/com/google/gson/metrics/NonUploadingCaliperRunner.java
deleted file mode 100644
index 80633e1408..0000000000
--- a/metrics/src/main/java/com/google/gson/metrics/NonUploadingCaliperRunner.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.google.gson.metrics;
-
-import com.google.caliper.runner.CaliperMain;
-
-class NonUploadingCaliperRunner {
- private static String[] concat(String first, String... others) {
- if (others.length == 0) {
- return new String[] { first };
- } else {
- String[] result = new String[others.length + 1];
- result[0] = first;
- System.arraycopy(others, 0, result, 1, others.length);
- return result;
- }
- }
-
- public static void run(Class> c, String[] args) {
- // Disable result upload; Caliper uploads results to webapp by default, see https://github.com/google/caliper/issues/356
- CaliperMain.main(c, concat("-Cresults.upload.options.url=", args));
- }
-}
diff --git a/metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java b/metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java
deleted file mode 100644
index e6a4530239..0000000000
--- a/metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * 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.google.gson.metrics;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonFactoryBuilder;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.MapperFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.json.JsonMapper;
-import com.google.caliper.BeforeExperiment;
-import com.google.caliper.Param;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonParser;
-import com.google.gson.annotations.SerializedName;
-import com.google.gson.reflect.TypeToken;
-import java.io.CharArrayReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.lang.reflect.Type;
-import java.net.URL;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-/**
- * Measure Gson and Jackson parsing and binding performance.
- *
- * This benchmark requires that ParseBenchmarkData.zip is on the classpath.
- * That file contains Twitter feed data, which is representative of what
- * applications will be parsing.
- */
-public final class ParseBenchmark {
- @Param Document document;
- @Param Api api;
-
- private enum Document {
- TWEETS(new TypeToken>() {}, new TypeReference>() {}),
- READER_SHORT(new TypeToken() {}, new TypeReference() {}),
- READER_LONG(new TypeToken() {}, new TypeReference() {});
-
- private final TypeToken> gsonType;
- private final TypeReference> jacksonType;
-
- private Document(TypeToken> typeToken, TypeReference> typeReference) {
- this.gsonType = typeToken;
- this.jacksonType = typeReference;
- }
- }
-
- private enum Api {
- JACKSON_STREAM {
- @Override Parser newParser() {
- return new JacksonStreamParser();
- }
- },
- JACKSON_BIND {
- @Override Parser newParser() {
- return new JacksonBindParser();
- }
- },
- GSON_STREAM {
- @Override Parser newParser() {
- return new GsonStreamParser();
- }
- },
- GSON_SKIP {
- @Override Parser newParser() {
- return new GsonSkipParser();
- }
- },
- GSON_DOM {
- @Override Parser newParser() {
- return new GsonDomParser();
- }
- },
- GSON_BIND {
- @Override Parser newParser() {
- return new GsonBindParser();
- }
- };
- abstract Parser newParser();
- }
-
- private char[] text;
- private Parser parser;
-
- @BeforeExperiment
- void setUp() throws Exception {
- text = resourceToString(document.name() + ".json").toCharArray();
- parser = api.newParser();
- }
-
- public void timeParse(int reps) throws Exception {
- for (int i = 0; i < reps; i++) {
- parser.parse(text, document);
- }
- }
-
- private static File getResourceFile(String path) throws Exception {
- URL url = ParseBenchmark.class.getResource(path);
- if (url == null) {
- throw new IllegalArgumentException("Resource " + path + " does not exist");
- }
- File file = new File(url.toURI());
- if (!file.isFile()) {
- throw new IllegalArgumentException("Resource " + path + " is not a file");
- }
- return file;
- }
-
- private static String resourceToString(String fileName) throws Exception {
- ZipFile zipFile = new ZipFile(getResourceFile("/ParseBenchmarkData.zip"));
- try {
- ZipEntry zipEntry = zipFile.getEntry(fileName);
- Reader reader = new InputStreamReader(zipFile.getInputStream(zipEntry));
- char[] buffer = new char[8192];
- StringWriter writer = new StringWriter();
- int count;
- while ((count = reader.read(buffer)) != -1) {
- writer.write(buffer, 0, count);
- }
- reader.close();
- return writer.toString();
-
- } finally {
- zipFile.close();
- }
- }
-
- public static void main(String[] args) throws Exception {
- NonUploadingCaliperRunner.run(ParseBenchmark.class, args);
- }
-
- interface Parser {
- void parse(char[] data, Document document) throws Exception;
- }
-
- private static class GsonStreamParser implements Parser {
- @Override
- public void parse(char[] data, Document document) throws Exception {
- com.google.gson.stream.JsonReader jsonReader
- = new com.google.gson.stream.JsonReader(new CharArrayReader(data));
- readToken(jsonReader);
- jsonReader.close();
- }
-
- private void readToken(com.google.gson.stream.JsonReader reader) throws IOException {
- while (true) {
- switch (reader.peek()) {
- case BEGIN_ARRAY:
- reader.beginArray();
- break;
- case END_ARRAY:
- reader.endArray();
- break;
- case BEGIN_OBJECT:
- reader.beginObject();
- break;
- case END_OBJECT:
- reader.endObject();
- break;
- case NAME:
- reader.nextName();
- break;
- case BOOLEAN:
- reader.nextBoolean();
- break;
- case NULL:
- reader.nextNull();
- break;
- case NUMBER:
- reader.nextLong();
- break;
- case STRING:
- reader.nextString();
- break;
- case END_DOCUMENT:
- return;
- default:
- throw new IllegalArgumentException("Unexpected token" + reader.peek());
- }
- }
- }
- }
-
- private static class GsonSkipParser implements Parser {
- @Override
- public void parse(char[] data, Document document) throws Exception {
- com.google.gson.stream.JsonReader jsonReader
- = new com.google.gson.stream.JsonReader(new CharArrayReader(data));
- jsonReader.skipValue();
- jsonReader.close();
- }
- }
-
- private static class JacksonStreamParser implements Parser {
- @Override
- public void parse(char[] data, Document document) throws Exception {
- JsonFactory jsonFactory = new JsonFactoryBuilder().configure(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES, false).build();
- com.fasterxml.jackson.core.JsonParser jp = jsonFactory.createParser(new CharArrayReader(data));
- int depth = 0;
- do {
- JsonToken token = jp.nextToken();
- switch (token) {
- case START_OBJECT:
- case START_ARRAY:
- depth++;
- break;
- case END_OBJECT:
- case END_ARRAY:
- depth--;
- break;
- case FIELD_NAME:
- jp.getCurrentName();
- break;
- case VALUE_STRING:
- jp.getText();
- break;
- case VALUE_NUMBER_INT:
- case VALUE_NUMBER_FLOAT:
- jp.getLongValue();
- break;
- case VALUE_TRUE:
- case VALUE_FALSE:
- jp.getBooleanValue();
- break;
- case VALUE_NULL:
- // Do nothing; nextToken() will advance in stream
- break;
- default:
- throw new IllegalArgumentException("Unexpected token " + token);
- }
- } while (depth > 0);
- jp.close();
- }
- }
-
- private static class GsonDomParser implements Parser {
- @Override
- public void parse(char[] data, Document document) throws Exception {
- JsonParser.parseReader(new CharArrayReader(data));
- }
- }
-
- private static class GsonBindParser implements Parser {
- private static Gson gson = new GsonBuilder()
- .setDateFormat("EEE MMM dd HH:mm:ss Z yyyy")
- .create();
-
- @Override
- public void parse(char[] data, Document document) throws Exception {
- gson.fromJson(new CharArrayReader(data), document.gsonType);
- }
- }
-
- private static class JacksonBindParser implements Parser {
- private static final ObjectMapper mapper;
-
- static {
- mapper = JsonMapper.builder()
- .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
- .configure(MapperFeature.AUTO_DETECT_FIELDS, true)
- .build();
- mapper.setDateFormat(new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.ENGLISH));
- }
-
- @Override
- public void parse(char[] data, Document document) throws Exception {
- mapper.readValue(new CharArrayReader(data), document.jacksonType);
- }
- }
-
- static class Tweet {
- @JsonProperty String coordinates;
- @JsonProperty boolean favorited;
- @JsonProperty Date created_at;
- @JsonProperty boolean truncated;
- @JsonProperty Tweet retweeted_status;
- @JsonProperty String id_str;
- @JsonProperty String in_reply_to_id_str;
- @JsonProperty String contributors;
- @JsonProperty String text;
- @JsonProperty long id;
- @JsonProperty String retweet_count;
- @JsonProperty String in_reply_to_status_id_str;
- @JsonProperty Object geo;
- @JsonProperty boolean retweeted;
- @JsonProperty String in_reply_to_user_id;
- @JsonProperty String in_reply_to_screen_name;
- @JsonProperty Object place;
- @JsonProperty User user;
- @JsonProperty String source;
- @JsonProperty String in_reply_to_user_id_str;
- }
-
- static class User {
- @JsonProperty String name;
- @JsonProperty String profile_sidebar_border_color;
- @JsonProperty boolean profile_background_tile;
- @JsonProperty String profile_sidebar_fill_color;
- @JsonProperty Date created_at;
- @JsonProperty String location;
- @JsonProperty String profile_image_url;
- @JsonProperty boolean follow_request_sent;
- @JsonProperty String profile_link_color;
- @JsonProperty boolean is_translator;
- @JsonProperty String id_str;
- @JsonProperty int favourites_count;
- @JsonProperty boolean contributors_enabled;
- @JsonProperty String url;
- @JsonProperty boolean default_profile;
- @JsonProperty long utc_offset;
- @JsonProperty long id;
- @JsonProperty boolean profile_use_background_image;
- @JsonProperty int listed_count;
- @JsonProperty String lang;
- @JsonProperty("protected") @SerializedName("protected") boolean isProtected;
- @JsonProperty int followers_count;
- @JsonProperty String profile_text_color;
- @JsonProperty String profile_background_color;
- @JsonProperty String time_zone;
- @JsonProperty String description;
- @JsonProperty boolean notifications;
- @JsonProperty boolean geo_enabled;
- @JsonProperty boolean verified;
- @JsonProperty String profile_background_image_url;
- @JsonProperty boolean defalut_profile_image;
- @JsonProperty int friends_count;
- @JsonProperty int statuses_count;
- @JsonProperty String screen_name;
- @JsonProperty boolean following;
- @JsonProperty boolean show_all_inline_media;
- }
-
- static class Feed {
- @JsonProperty String id;
- @JsonProperty String title;
- @JsonProperty String description;
- @JsonProperty("alternate") @SerializedName("alternate") List alternates;
- @JsonProperty long updated;
- @JsonProperty List- items;
-
- @Override public String toString() {
- StringBuilder result = new StringBuilder()
- .append(id)
- .append("\n").append(title)
- .append("\n").append(description)
- .append("\n").append(alternates)
- .append("\n").append(updated);
- int i = 1;
- for (Item item : items) {
- result.append(i++).append(": ").append(item).append("\n\n");
- }
- return result.toString();
- }
- }
-
- static class Link {
- @JsonProperty String href;
-
- @Override public String toString() {
- return href;
- }
- }
-
- static class Item {
- @JsonProperty List
categories;
- @JsonProperty String title;
- @JsonProperty long published;
- @JsonProperty long updated;
- @JsonProperty("alternate") @SerializedName("alternate") List alternates;
- @JsonProperty Content content;
- @JsonProperty String author;
- @JsonProperty List likingUsers;
-
- @Override public String toString() {
- return title
- + "\nauthor: " + author
- + "\npublished: " + published
- + "\nupdated: " + updated
- + "\n" + content
- + "\nliking users: " + likingUsers
- + "\nalternates: " + alternates
- + "\ncategories: " + categories;
- }
- }
-
- static class Content {
- @JsonProperty String content;
-
- @Override public String toString() {
- return content;
- }
- }
-
- static class ReaderUser {
- @JsonProperty String userId;
-
- @Override public String toString() {
- return userId;
- }
- }
-}
diff --git a/metrics/src/main/java/com/google/gson/metrics/SerializationBenchmark.java b/metrics/src/main/java/com/google/gson/metrics/SerializationBenchmark.java
deleted file mode 100644
index bf67a66b05..0000000000
--- a/metrics/src/main/java/com/google/gson/metrics/SerializationBenchmark.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * 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.google.gson.metrics;
-
-import com.google.caliper.BeforeExperiment;
-import com.google.caliper.Param;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-/**
- * Caliper based micro benchmarks for Gson serialization
- *
- * @author Inderjeet Singh
- * @author Jesse Wilson
- * @author Joel Leitch
- */
-public class SerializationBenchmark {
-
- private Gson gson;
- private BagOfPrimitives bag;
- @Param
- private boolean pretty;
-
- public static void main(String[] args) {
- NonUploadingCaliperRunner.run(SerializationBenchmark.class, args);
- }
-
- @BeforeExperiment
- void setUp() throws Exception {
- this.gson = pretty ? new GsonBuilder().setPrettyPrinting().create() : new Gson();
- this.bag = new BagOfPrimitives(10L, 1, false, "foo");
- }
-
- public void timeObjectSerialization(int reps) {
- for (int i=0; i
gson
- extras
- metrics
- proto
diff --git a/proto/.gitignore b/proto/.gitignore
deleted file mode 100644
index f44578ac2b..0000000000
--- a/proto/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-src/main/java/com/google/gson/protobuf/generated/
diff --git a/proto/README.md b/proto/README.md
deleted file mode 100644
index c6f7906a68..0000000000
--- a/proto/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# proto
-
-This Maven module contains the source code for a JSON serializer and deserializer for
-[Protocol Buffers (protobuf)](https://developers.google.com/protocol-buffers/docs/javatutorial)
-messages.
-
-The artifacts created by this module are currently not deployed to Maven Central.
diff --git a/proto/pom.xml b/proto/pom.xml
deleted file mode 100644
index 74ab60c8ed..0000000000
--- a/proto/pom.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-
-
-
-
- 4.0.0
-
- com.google.code.gson
- gson-parent
- 2.10.1
-
-
- proto
- Gson Protobuf Support
- Gson support for Protobufs
-
-
-
- Apache-2.0
- https://www.apache.org/licenses/LICENSE-2.0.txt
-
-
-
-
-
- com.google.code.gson
- gson
- ${project.parent.version}
-
-
-
- com.google.protobuf
- protobuf-java
- 4.0.0-rc-2
-
-
-
- com.google.guava
- guava
- 31.1-jre
-
-
-
- junit
- junit
- test
-
-
-
- com.google.truth
- truth
- 1.1.3
- test
-
-
-
-
- gson-proto
-
-
-
- kr.motd.maven
- os-maven-plugin
- 1.7.1
-
-
-
-
-
- org.xolstice.maven.plugins
- protobuf-maven-plugin
- 0.6.1
-
- com.google.protobuf:protoc:3.17.3:exe:${os.detected.classifier}
-
-
-
-
- test-compile
-
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-deploy-plugin
-
-
- true
-
-
-
-
-
-
-
-
- Inderjeet Singh
- Google Inc.
-
-
-
diff --git a/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java b/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java
deleted file mode 100644
index 9aa166fc68..0000000000
--- a/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.google.gson.protobuf;
-
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.base.CaseFormat;
-import com.google.common.collect.MapMaker;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import com.google.protobuf.DescriptorProtos.EnumValueOptions;
-import com.google.protobuf.DescriptorProtos.FieldOptions;
-import com.google.protobuf.Descriptors.Descriptor;
-import com.google.protobuf.Descriptors.EnumDescriptor;
-import com.google.protobuf.Descriptors.EnumValueDescriptor;
-import com.google.protobuf.Descriptors.FieldDescriptor;
-import com.google.protobuf.DynamicMessage;
-import com.google.protobuf.Extension;
-import com.google.protobuf.Message;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * GSON type adapter for protocol buffers that knows how to serialize enums either by using their
- * values or their names, and also supports custom proto field names.
- *
- * You can specify which case representation is used for the proto fields when writing/reading the
- * JSON payload by calling {@link Builder#setFieldNameSerializationFormat(CaseFormat, CaseFormat)}.
- *
- * An example of default serialization/deserialization using custom proto field names is shown
- * below:
- *
- *
- * message MyMessage {
- * // Will be serialized as 'osBuildID' instead of the default 'osBuildId'.
- * string os_build_id = 1 [(serialized_name) = "osBuildID"];
- * }
- *
- *
- * @author Inderjeet Singh
- * @author Emmanuel Cron
- * @author Stanley Wang
- */
-public class ProtoTypeAdapter
- implements JsonSerializer, JsonDeserializer {
- /**
- * Determines how enum values should be serialized.
- */
- public enum EnumSerialization {
- /**
- * Serializes and deserializes enum values using their number . When this is used, custom
- * value names set on enums are ignored.
- */
- NUMBER,
- /** Serializes and deserializes enum values using their name . */
- NAME;
- }
-
- /**
- * Builder for {@link ProtoTypeAdapter}s.
- */
- public static class Builder {
- private final Set> serializedNameExtensions;
- private final Set> serializedEnumValueExtensions;
- private EnumSerialization enumSerialization;
- private CaseFormat protoFormat;
- private CaseFormat jsonFormat;
-
- private Builder(EnumSerialization enumSerialization, CaseFormat fromFieldNameFormat,
- CaseFormat toFieldNameFormat) {
- this.serializedNameExtensions = new HashSet<>();
- this.serializedEnumValueExtensions = new HashSet<>();
- setEnumSerialization(enumSerialization);
- setFieldNameSerializationFormat(fromFieldNameFormat, toFieldNameFormat);
- }
-
- public Builder setEnumSerialization(EnumSerialization enumSerialization) {
- this.enumSerialization = requireNonNull(enumSerialization);
- return this;
- }
-
- /**
- * Sets the field names serialization format. The first parameter defines how to read the format
- * of the proto field names you are converting to JSON. The second parameter defines which
- * format to use when serializing them.
- *
- * For example, if you use the following parameters: {@link CaseFormat#LOWER_UNDERSCORE},
- * {@link CaseFormat#LOWER_CAMEL}, the following conversion will occur:
- *
- *
{@code
- * PROTO <-> JSON
- * my_field myField
- * foo foo
- * n__id_ct nIdCt
- * }
- */
- public Builder setFieldNameSerializationFormat(CaseFormat fromFieldNameFormat,
- CaseFormat toFieldNameFormat) {
- this.protoFormat = fromFieldNameFormat;
- this.jsonFormat = toFieldNameFormat;
- return this;
- }
-
- /**
- * Adds a field proto annotation that, when set, overrides the default field name
- * serialization/deserialization. For example, if you add the '{@code serialized_name}'
- * annotation and you define a field in your proto like the one below:
- *
- *
- * string client_app_id = 1 [(serialized_name) = "appId"];
- *
- *
- * ...the adapter will serialize the field using '{@code appId}' instead of the default '
- * {@code clientAppId}'. This lets you customize the name serialization of any proto field.
- */
- public Builder addSerializedNameExtension(
- Extension serializedNameExtension) {
- serializedNameExtensions.add(requireNonNull(serializedNameExtension));
- return this;
- }
-
- /**
- * Adds an enum value proto annotation that, when set, overrides the default enum value
- * serialization/deserialization of this adapter. For example, if you add the '
- * {@code serialized_value}' annotation and you define an enum in your proto like the one below:
- *
- *
- * enum MyEnum {
- * UNKNOWN = 0;
- * CLIENT_APP_ID = 1 [(serialized_value) = "APP_ID"];
- * TWO = 2 [(serialized_value) = "2"];
- * }
- *
- *
- * ...the adapter will serialize the value {@code CLIENT_APP_ID} as "{@code APP_ID}" and the
- * value {@code TWO} as "{@code 2}". This works for both serialization and deserialization.
- *
- * Note that you need to set the enum serialization of this adapter to
- * {@link EnumSerialization#NAME}, otherwise these annotations will be ignored.
- */
- public Builder addSerializedEnumValueExtension(
- Extension serializedEnumValueExtension) {
- serializedEnumValueExtensions.add(requireNonNull(serializedEnumValueExtension));
- return this;
- }
-
- public ProtoTypeAdapter build() {
- return new ProtoTypeAdapter(enumSerialization, protoFormat, jsonFormat,
- serializedNameExtensions, serializedEnumValueExtensions);
- }
- }
-
- /**
- * Creates a new {@link ProtoTypeAdapter} builder, defaulting enum serialization to
- * {@link EnumSerialization#NAME} and converting field serialization from
- * {@link CaseFormat#LOWER_UNDERSCORE} to {@link CaseFormat#LOWER_CAMEL}.
- */
- public static Builder newBuilder() {
- return new Builder(EnumSerialization.NAME, CaseFormat.LOWER_UNDERSCORE, CaseFormat.LOWER_CAMEL);
- }
-
- private static final com.google.protobuf.Descriptors.FieldDescriptor.Type ENUM_TYPE =
- com.google.protobuf.Descriptors.FieldDescriptor.Type.ENUM;
-
- private static final ConcurrentMap, Method>> mapOfMapOfMethods =
- new MapMaker().makeMap();
-
- private final EnumSerialization enumSerialization;
- private final CaseFormat protoFormat;
- private final CaseFormat jsonFormat;
- private final Set> serializedNameExtensions;
- private final Set> serializedEnumValueExtensions;
-
- private ProtoTypeAdapter(EnumSerialization enumSerialization,
- CaseFormat protoFormat,
- CaseFormat jsonFormat,
- Set> serializedNameExtensions,
- Set> serializedEnumValueExtensions) {
- this.enumSerialization = enumSerialization;
- this.protoFormat = protoFormat;
- this.jsonFormat = jsonFormat;
- this.serializedNameExtensions = serializedNameExtensions;
- this.serializedEnumValueExtensions = serializedEnumValueExtensions;
- }
-
- @Override
- public JsonElement serialize(Message src, Type typeOfSrc,
- JsonSerializationContext context) {
- JsonObject ret = new JsonObject();
- final Map fields = src.getAllFields();
-
- for (Map.Entry fieldPair : fields.entrySet()) {
- final FieldDescriptor desc = fieldPair.getKey();
- String name = getCustSerializedName(desc.getOptions(), desc.getName());
-
- if (desc.getType() == ENUM_TYPE) {
- // Enum collections are also returned as ENUM_TYPE
- if (fieldPair.getValue() instanceof Collection) {
- // Build the array to avoid infinite loop
- JsonArray array = new JsonArray();
- @SuppressWarnings("unchecked")
- Collection enumDescs =
- (Collection) fieldPair.getValue();
- for (EnumValueDescriptor enumDesc : enumDescs) {
- array.add(context.serialize(getEnumValue(enumDesc)));
- ret.add(name, array);
- }
- } else {
- EnumValueDescriptor enumDesc = ((EnumValueDescriptor) fieldPair.getValue());
- ret.add(name, context.serialize(getEnumValue(enumDesc)));
- }
- } else {
- ret.add(name, context.serialize(fieldPair.getValue()));
- }
- }
- return ret;
- }
-
- @Override
- public Message deserialize(JsonElement json, Type typeOfT,
- JsonDeserializationContext context) throws JsonParseException {
- try {
- JsonObject jsonObject = json.getAsJsonObject();
- @SuppressWarnings("unchecked")
- Class extends Message> protoClass = (Class extends Message>) typeOfT;
-
- if (DynamicMessage.class.isAssignableFrom(protoClass)) {
- throw new IllegalStateException("only generated messages are supported");
- }
-
- try {
- // Invoke the ProtoClass.newBuilder() method
- Message.Builder protoBuilder =
- (Message.Builder) getCachedMethod(protoClass, "newBuilder").invoke(null);
-
- Message defaultInstance =
- (Message) getCachedMethod(protoClass, "getDefaultInstance").invoke(null);
-
- Descriptor protoDescriptor =
- (Descriptor) getCachedMethod(protoClass, "getDescriptor").invoke(null);
- // Call setters on all of the available fields
- for (FieldDescriptor fieldDescriptor : protoDescriptor.getFields()) {
- String jsonFieldName =
- getCustSerializedName(fieldDescriptor.getOptions(), fieldDescriptor.getName());
-
- JsonElement jsonElement = jsonObject.get(jsonFieldName);
- if (jsonElement != null && !jsonElement.isJsonNull()) {
- // Do not reuse jsonFieldName here, it might have a custom value
- Object fieldValue;
- if (fieldDescriptor.getType() == ENUM_TYPE) {
- if (jsonElement.isJsonArray()) {
- // Handling array
- Collection enumCollection =
- new ArrayList<>(jsonElement.getAsJsonArray().size());
- for (JsonElement element : jsonElement.getAsJsonArray()) {
- enumCollection.add(
- findValueByNameAndExtension(fieldDescriptor.getEnumType(), element));
- }
- fieldValue = enumCollection;
- } else {
- // No array, just a plain value
- fieldValue =
- findValueByNameAndExtension(fieldDescriptor.getEnumType(), jsonElement);
- }
- protoBuilder.setField(fieldDescriptor, fieldValue);
- } else if (fieldDescriptor.isRepeated()) {
- // If the type is an array, then we have to grab the type from the class.
- // protobuf java field names are always lower camel case
- String protoArrayFieldName =
- protoFormat.to(CaseFormat.LOWER_CAMEL, fieldDescriptor.getName()) + "_";
- Field protoArrayField = protoClass.getDeclaredField(protoArrayFieldName);
- Type protoArrayFieldType = protoArrayField.getGenericType();
- fieldValue = context.deserialize(jsonElement, protoArrayFieldType);
- protoBuilder.setField(fieldDescriptor, fieldValue);
- } else {
- Object field = defaultInstance.getField(fieldDescriptor);
- fieldValue = context.deserialize(jsonElement, field.getClass());
- protoBuilder.setField(fieldDescriptor, fieldValue);
- }
- }
- }
- return protoBuilder.build();
- } catch (SecurityException e) {
- throw new JsonParseException(e);
- } catch (NoSuchMethodException e) {
- throw new JsonParseException(e);
- } catch (IllegalArgumentException e) {
- throw new JsonParseException(e);
- } catch (IllegalAccessException e) {
- throw new JsonParseException(e);
- } catch (InvocationTargetException e) {
- throw new JsonParseException(e);
- }
- } catch (Exception e) {
- throw new JsonParseException("Error while parsing proto", e);
- }
- }
-
- /**
- * Retrieves the custom field name from the given options, and if not found, returns the specified
- * default name.
- */
- private String getCustSerializedName(FieldOptions options, String defaultName) {
- for (Extension extension : serializedNameExtensions) {
- if (options.hasExtension(extension)) {
- return options.getExtension(extension);
- }
- }
- return protoFormat.to(jsonFormat, defaultName);
- }
-
- /**
- * Retrieves the custom enum value name from the given options, and if not found, returns the
- * specified default value.
- */
- private String getCustSerializedEnumValue(EnumValueOptions options, String defaultValue) {
- for (Extension extension : serializedEnumValueExtensions) {
- if (options.hasExtension(extension)) {
- return options.getExtension(extension);
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns the enum value to use for serialization, depending on the value of
- * {@link EnumSerialization} that was given to this adapter.
- */
- private Object getEnumValue(EnumValueDescriptor enumDesc) {
- if (enumSerialization == EnumSerialization.NAME) {
- return getCustSerializedEnumValue(enumDesc.getOptions(), enumDesc.getName());
- } else {
- return enumDesc.getNumber();
- }
- }
-
- /**
- * Finds an enum value in the given {@link EnumDescriptor} that matches the given JSON element,
- * either by name if the current adapter is using {@link EnumSerialization#NAME}, otherwise by
- * number. If matching by name, it uses the extension value if it is defined, otherwise it uses
- * its default value.
- *
- * @throws IllegalArgumentException if a matching name/number was not found
- */
- private EnumValueDescriptor findValueByNameAndExtension(EnumDescriptor desc,
- JsonElement jsonElement) {
- if (enumSerialization == EnumSerialization.NAME) {
- // With enum name
- for (EnumValueDescriptor enumDesc : desc.getValues()) {
- String enumValue = getCustSerializedEnumValue(enumDesc.getOptions(), enumDesc.getName());
- if (enumValue.equals(jsonElement.getAsString())) {
- return enumDesc;
- }
- }
- throw new IllegalArgumentException(
- String.format("Unrecognized enum name: %s", jsonElement.getAsString()));
- } else {
- // With enum value
- EnumValueDescriptor fieldValue = desc.findValueByNumber(jsonElement.getAsInt());
- if (fieldValue == null) {
- throw new IllegalArgumentException(
- String.format("Unrecognized enum value: %d", jsonElement.getAsInt()));
- }
- return fieldValue;
- }
- }
-
- private static Method getCachedMethod(Class> clazz, String methodName,
- Class>... methodParamTypes) throws NoSuchMethodException {
- ConcurrentMap, Method> mapOfMethods = mapOfMapOfMethods.get(methodName);
- if (mapOfMethods == null) {
- mapOfMethods = new MapMaker().makeMap();
- ConcurrentMap, Method> previous =
- mapOfMapOfMethods.putIfAbsent(methodName, mapOfMethods);
- mapOfMethods = previous == null ? mapOfMethods : previous;
- }
-
- Method method = mapOfMethods.get(clazz);
- if (method == null) {
- method = clazz.getMethod(methodName, methodParamTypes);
- mapOfMethods.putIfAbsent(clazz, method);
- // NB: it doesn't matter which method we return in the event of a race.
- }
- return method;
- }
-
-}
diff --git a/proto/src/test/java/com/google/gson/protobuf/functional/ProtosWithAnnotationsTest.java b/proto/src/test/java/com/google/gson/protobuf/functional/ProtosWithAnnotationsTest.java
deleted file mode 100644
index 7fb92e89b4..0000000000
--- a/proto/src/test/java/com/google/gson/protobuf/functional/ProtosWithAnnotationsTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.google.gson.protobuf.functional;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import com.google.common.base.CaseFormat;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonParseException;
-import com.google.gson.protobuf.ProtoTypeAdapter;
-import com.google.gson.protobuf.ProtoTypeAdapter.EnumSerialization;
-import com.google.gson.protobuf.generated.Annotations;
-import com.google.gson.protobuf.generated.Bag.OuterMessage;
-import com.google.gson.protobuf.generated.Bag.ProtoWithAnnotations;
-import com.google.gson.protobuf.generated.Bag.ProtoWithAnnotations.InnerMessage;
-import com.google.gson.protobuf.generated.Bag.ProtoWithAnnotations.InnerMessage.Data;
-import com.google.gson.protobuf.generated.Bag.ProtoWithAnnotations.InnerMessage.Type;
-import com.google.protobuf.GeneratedMessageV3;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Functional tests for protocol buffers using annotations for field names and enum values.
- *
- * @author Emmanuel Cron
- */
-public class ProtosWithAnnotationsTest {
- private Gson gson;
- private Gson gsonWithEnumNumbers;
- private Gson gsonWithLowerHyphen;
-
- @Before
- public void setUp() throws Exception {
- ProtoTypeAdapter.Builder protoTypeAdapter = ProtoTypeAdapter.newBuilder()
- .setEnumSerialization(EnumSerialization.NAME)
- .addSerializedNameExtension(Annotations.serializedName)
- .addSerializedEnumValueExtension(Annotations.serializedValue);
- gson = new GsonBuilder()
- .registerTypeHierarchyAdapter(GeneratedMessageV3.class, protoTypeAdapter.build())
- .create();
- gsonWithEnumNumbers = new GsonBuilder()
- .registerTypeHierarchyAdapter(GeneratedMessageV3.class, protoTypeAdapter
- .setEnumSerialization(EnumSerialization.NUMBER)
- .build())
- .create();
- gsonWithLowerHyphen = new GsonBuilder()
- .registerTypeHierarchyAdapter(GeneratedMessageV3.class, protoTypeAdapter
- .setFieldNameSerializationFormat(CaseFormat.LOWER_UNDERSCORE, CaseFormat.LOWER_HYPHEN)
- .build())
- .create();
- }
-
- @Test
- public void testProtoWithAnnotations_deserialize() {
- String json = String.format("{ %n"
- + " \"id\":\"41e5e7fd6065d101b97018a465ffff01\",%n"
- + " \"expiration_date\":{ %n"
- + " \"month\":\"12\",%n"
- + " \"year\":\"2017\",%n"
- + " \"timeStamp\":\"9864653135687\",%n"
- + " \"countryCode5f55\":\"en_US\"%n"
- + " },%n"
- // Don't define innerMessage1
- + " \"innerMessage2\":{ %n"
- // Set a number as a string; it should work
- + " \"nIdCt\":\"98798465\",%n"
- + " \"content\":\"text/plain\",%n"
- + " \"$binary_data$\":[ %n"
- + " { %n"
- + " \"data\":\"OFIN8e9fhwoeh8((⁹8efywoih\",%n"
- // Don't define width
- + " \"height\":665%n"
- + " },%n"
- + " { %n"
- // Define as an int; it should work
- + " \"data\":65,%n"
- + " \"width\":-56684%n"
- // Don't define height
- + " }%n"
- + " ]%n"
- + " },%n"
- // Define a bunch of non recognizable data
- + " \"non_existing\":\"foobar\",%n"
- + " \"stillNot\":{ %n"
- + " \"bunch\":\"of_useless data\"%n"
- + " }%n"
- + "}");
- ProtoWithAnnotations proto = gson.fromJson(json, ProtoWithAnnotations.class);
- assertThat(proto.getId()).isEqualTo("41e5e7fd6065d101b97018a465ffff01");
- assertThat(proto.getOuterMessage()).isEqualTo(OuterMessage.newBuilder()
- .setMonth(12)
- .setYear(2017)
- .setLongTimestamp(9864653135687L)
- .setCountryCode5F55("en_US")
- .build());
- assertThat(proto.hasInnerMessage1()).isFalse();
- assertThat(proto.getInnerMessage2()).isEqualTo(InnerMessage.newBuilder()
- .setNIdCt(98798465)
- .setContent(Type.TEXT)
- .addData(Data.newBuilder()
- .setData("OFIN8e9fhwoeh8((⁹8efywoih")
- .setHeight(665))
- .addData(Data.newBuilder()
- .setData("65")
- .setWidth(-56684))
- .build());
-
- String rebuilt = gson.toJson(proto);
- assertThat(rebuilt).isEqualTo("{"
- + "\"id\":\"41e5e7fd6065d101b97018a465ffff01\","
- + "\"expiration_date\":{"
- + "\"month\":12,"
- + "\"year\":2017,"
- + "\"timeStamp\":9864653135687,"
- + "\"countryCode5f55\":\"en_US\""
- + "},"
- + "\"innerMessage2\":{"
- + "\"nIdCt\":98798465,"
- + "\"content\":\"text/plain\","
- + "\"$binary_data$\":["
- + "{"
- + "\"data\":\"OFIN8e9fhwoeh8((⁹8efywoih\","
- + "\"height\":665"
- + "},"
- + "{"
- + "\"data\":\"65\","
- + "\"width\":-56684"
- + "}]}}");
- }
-
- @Test
- public void testProtoWithAnnotations_deserializeUnknownEnumValue() {
- String json = String.format("{ %n"
- + " \"content\":\"UNKNOWN\"%n"
- + "}");
- InnerMessage proto = gson.fromJson(json, InnerMessage.class);
- assertThat(proto.getContent()).isEqualTo(Type.UNKNOWN);
- }
-
- @Test
- public void testProtoWithAnnotations_deserializeUnrecognizedEnumValue() {
- String json = String.format("{ %n"
- + " \"content\":\"UNRECOGNIZED\"%n"
- + "}");
- try {
- gson.fromJson(json, InnerMessage.class);
- assertWithMessage("Should have thrown").fail();
- } catch (JsonParseException e) {
- // expected
- }
- }
-
- @Test
- public void testProtoWithAnnotations_deserializeWithEnumNumbers() {
- String json = String.format("{ %n"
- + " \"content\":\"0\"%n"
- + "}");
- InnerMessage proto = gsonWithEnumNumbers.fromJson(json, InnerMessage.class);
- assertThat(proto.getContent()).isEqualTo(Type.UNKNOWN);
- String rebuilt = gsonWithEnumNumbers.toJson(proto);
- assertThat(rebuilt).isEqualTo("{\"content\":0}");
-
- json = String.format("{ %n"
- + " \"content\":\"2\"%n"
- + "}");
- proto = gsonWithEnumNumbers.fromJson(json, InnerMessage.class);
- assertThat(proto.getContent()).isEqualTo(Type.IMAGE);
- rebuilt = gsonWithEnumNumbers.toJson(proto);
- assertThat(rebuilt).isEqualTo("{\"content\":2}");
- }
-
- @Test
- public void testProtoWithAnnotations_serialize() {
- ProtoWithAnnotations proto = ProtoWithAnnotations.newBuilder()
- .setId("09f3j20839h032y0329hf30932h0nffn")
- .setOuterMessage(OuterMessage.newBuilder()
- .setMonth(14)
- .setYear(6650)
- .setLongTimestamp(468406876880768L))
- .setInnerMessage1(InnerMessage.newBuilder()
- .setNIdCt(12)
- .setContent(Type.IMAGE)
- .addData(Data.newBuilder()
- .setData("data$$")
- .setWidth(200))
- .addData(Data.newBuilder()
- .setHeight(56)))
- .build();
-
- String json = gsonWithLowerHyphen.toJson(proto);
- assertThat(json).isEqualTo(
- "{\"id\":\"09f3j20839h032y0329hf30932h0nffn\","
- + "\"expiration_date\":{"
- + "\"month\":14,"
- + "\"year\":6650,"
- + "\"timeStamp\":468406876880768"
- + "},"
- // This field should be using hyphens
- + "\"inner-message-1\":{"
- + "\"n--id-ct\":12,"
- + "\"content\":2,"
- + "\"$binary_data$\":["
- + "{"
- + "\"data\":\"data$$\","
- + "\"width\":200"
- + "},"
- + "{"
- + "\"height\":56"
- + "}]"
- + "}"
- + "}");
-
- ProtoWithAnnotations rebuilt = gsonWithLowerHyphen.fromJson(json, ProtoWithAnnotations.class);
- assertThat(rebuilt).isEqualTo(proto);
- }
-}
diff --git a/proto/src/test/java/com/google/gson/protobuf/functional/ProtosWithComplexAndRepeatedFieldsTest.java b/proto/src/test/java/com/google/gson/protobuf/functional/ProtosWithComplexAndRepeatedFieldsTest.java
deleted file mode 100644
index 53b1fe368b..0000000000
--- a/proto/src/test/java/com/google/gson/protobuf/functional/ProtosWithComplexAndRepeatedFieldsTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.google.gson.protobuf.functional;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import com.google.common.base.CaseFormat;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonObject;
-import com.google.gson.protobuf.ProtoTypeAdapter;
-import com.google.gson.protobuf.ProtoTypeAdapter.EnumSerialization;
-import com.google.gson.protobuf.generated.Bag.ProtoWithDifferentCaseFormat;
-import com.google.gson.protobuf.generated.Bag.ProtoWithRepeatedFields;
-import com.google.gson.protobuf.generated.Bag.SimpleProto;
-import com.google.protobuf.GeneratedMessageV3;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Functional tests for protocol buffers using complex and repeated fields
- *
- * @author Inderjeet Singh
- */
-public class ProtosWithComplexAndRepeatedFieldsTest {
- private Gson gson;
- private Gson upperCamelGson;
-
- @Before
- public void setUp() throws Exception {
- gson =
- new GsonBuilder()
- .registerTypeHierarchyAdapter(GeneratedMessageV3.class,
- ProtoTypeAdapter.newBuilder()
- .setEnumSerialization(EnumSerialization.NUMBER)
- .build())
- .create();
- upperCamelGson =
- new GsonBuilder()
- .registerTypeHierarchyAdapter(
- GeneratedMessageV3.class, ProtoTypeAdapter.newBuilder()
- .setFieldNameSerializationFormat(
- CaseFormat.LOWER_UNDERSCORE, CaseFormat.UPPER_CAMEL)
- .build())
- .create();
- }
-
- @Test
- public void testSerializeRepeatedFields() {
- ProtoWithRepeatedFields proto = ProtoWithRepeatedFields.newBuilder()
- .addNumbers(2)
- .addNumbers(3)
- .addSimples(SimpleProto.newBuilder().setMsg("foo").build())
- .addSimples(SimpleProto.newBuilder().setCount(3).build())
- .build();
- String json = gson.toJson(proto);
- assertTrue(json.contains("[2,3]"));
- assertTrue(json.contains("foo"));
- assertTrue(json.contains("count"));
- }
-
- @Test
- public void testDeserializeRepeatedFieldsProto() {
- String json = "{numbers:[4,6],simples:[{msg:'bar'},{count:7}]}";
- ProtoWithRepeatedFields proto =
- gson.fromJson(json, ProtoWithRepeatedFields.class);
- assertEquals(4, proto.getNumbers(0));
- assertEquals(6, proto.getNumbers(1));
- assertEquals("bar", proto.getSimples(0).getMsg());
- assertEquals(7, proto.getSimples(1).getCount());
- }
-
- @Test
- public void testSerializeDifferentCaseFormat() {
- final ProtoWithDifferentCaseFormat proto =
- ProtoWithDifferentCaseFormat.newBuilder()
- .setAnotherField("foo")
- .addNameThatTestsCaseFormat("bar")
- .build();
- final JsonObject json = upperCamelGson.toJsonTree(proto).getAsJsonObject();
- assertEquals("foo", json.get("AnotherField").getAsString());
- assertEquals("bar", json.get("NameThatTestsCaseFormat").getAsJsonArray().get(0).getAsString());
- }
-
- @Test
- public void testDeserializeDifferentCaseFormat() {
- final String json = "{NameThatTestsCaseFormat:['bar'],AnotherField:'foo'}";
- ProtoWithDifferentCaseFormat proto =
- upperCamelGson.fromJson(json, ProtoWithDifferentCaseFormat.class);
- assertEquals("foo", proto.getAnotherField());
- assertEquals("bar", proto.getNameThatTestsCaseFormat(0));
- }
-}
diff --git a/proto/src/test/java/com/google/gson/protobuf/functional/ProtosWithPrimitiveTypesTest.java b/proto/src/test/java/com/google/gson/protobuf/functional/ProtosWithPrimitiveTypesTest.java
deleted file mode 100644
index 0666a6dd00..0000000000
--- a/proto/src/test/java/com/google/gson/protobuf/functional/ProtosWithPrimitiveTypesTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc.
- *
- * 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.google.gson.protobuf.functional;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.protobuf.ProtoTypeAdapter;
-import com.google.gson.protobuf.ProtoTypeAdapter.EnumSerialization;
-import com.google.gson.protobuf.generated.Bag.SimpleProto;
-import com.google.protobuf.Descriptors.Descriptor;
-import com.google.protobuf.GeneratedMessageV3;
-import org.junit.Before;
-import org.junit.Test;
-
-public class ProtosWithPrimitiveTypesTest {
- private Gson gson;
-
- @Before
- public void setUp() throws Exception {
- gson = new GsonBuilder().registerTypeHierarchyAdapter(
- GeneratedMessageV3.class, ProtoTypeAdapter.newBuilder()
- .setEnumSerialization(EnumSerialization.NUMBER)
- .build())
- .create();
- }
-
- @Test
- public void testSerializeEmptyProto() {
- SimpleProto proto = SimpleProto.newBuilder().build();
- String json = gson.toJson(proto);
- assertEquals("{}", json);
- }
-
- @Test
- public void testDeserializeEmptyProto() {
- SimpleProto proto = gson.fromJson("{}", SimpleProto.class);
- assertFalse(proto.hasCount());
- assertFalse(proto.hasMsg());
- }
-
- @Test
- public void testSerializeProto() {
- Descriptor descriptor = SimpleProto.getDescriptor();
- SimpleProto proto = SimpleProto.newBuilder()
- .setCount(3)
- .setMsg("foo")
- .build();
- String json = gson.toJson(proto);
- assertTrue(json.contains("\"msg\":\"foo\""));
- assertTrue(json.contains("\"count\":3"));
- }
-
- @Test
- public void testDeserializeProto() {
- SimpleProto proto = gson.fromJson("{msg:'foo',count:3}", SimpleProto.class);
- assertEquals("foo", proto.getMsg());
- assertEquals(3, proto.getCount());
- }
-
- @Test
- public void testDeserializeWithExplicitNullValue() {
- SimpleProto proto = gson.fromJson("{msg:'foo',count:null}", SimpleProto.class);
- assertEquals("foo", proto.getMsg());
- assertEquals(0, proto.getCount());
- }
-
-}
diff --git a/proto/src/test/proto/annotations.proto b/proto/src/test/proto/annotations.proto
deleted file mode 100644
index 53b727a666..0000000000
--- a/proto/src/test/proto/annotations.proto
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Copyright (C) 2010 Google Inc.
-//
-// 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.
-//
-
-syntax = "proto2";
-
-package google.gson.protobuf.generated;
-option java_package = "com.google.gson.protobuf.generated";
-
-import "google/protobuf/descriptor.proto";
-
-extend google.protobuf.FieldOptions {
- // Indicates a field name that overrides the default for serialization
- optional string serialized_name = 92066888;
-}
-
-extend google.protobuf.EnumValueOptions {
- // Indicates a field value that overrides the default for serialization
- optional string serialized_value = 92066888;
-}
diff --git a/proto/src/test/proto/bag.proto b/proto/src/test/proto/bag.proto
deleted file mode 100644
index 3e4769e2a8..0000000000
--- a/proto/src/test/proto/bag.proto
+++ /dev/null
@@ -1,72 +0,0 @@
-//
-// Copyright (C) 2010 Google Inc.
-//
-// 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.
-//
-
-syntax = "proto2";
-
-package google.gson.protobuf.generated;
-option java_package = "com.google.gson.protobuf.generated";
-
-import "annotations.proto";
-
-message SimpleProto {
- optional string msg = 1;
- optional int32 count = 2;
-}
-
-message ProtoWithDifferentCaseFormat {
- repeated string name_that_tests_case_format = 1;
- optional string another_field = 2;
-}
-
-message ProtoWithRepeatedFields {
- repeated int64 numbers = 1;
- repeated SimpleProto simples = 2;
- optional string name = 3;
-}
-
-// -- A more complex message with annotations and nested protos
-
-message OuterMessage {
- optional int32 month = 1;
- optional int32 year = 2;
- optional int64 long_timestamp = 3 [(serialized_name) = "timeStamp"];
- optional string country_code_5f55 = 4;
-}
-
-message ProtoWithAnnotations {
- optional string id = 1;
- optional OuterMessage outer_message = 2 [(serialized_name) = "expiration_date"];
-
- message InnerMessage {
- optional int32 n__id_ct = 1;
-
- enum Type {
- UNKNOWN = 0;
- TEXT = 1 [(serialized_value) = "text/plain"];
- IMAGE = 2 [(serialized_value) = "image/png"];
- }
- optional Type content = 2;
-
- message Data {
- optional string data = 1;
- optional int32 width = 2;
- optional int32 height = 3;
- }
- repeated Data data = 3 [(serialized_name) = "$binary_data$"];
- }
- optional InnerMessage inner_message_1 = 3;
- optional InnerMessage inner_message_2 = 4;
-}
\ No newline at end of file