diff --git a/core/pom.xml b/core/pom.xml
index 4cb265ec21..22a5182131 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -106,7 +106,7 @@
com.google.code.gson
gson
- 1.6
+ 1.7.1
com.google.guava
diff --git a/core/src/main/java/com/google/gson/JcloudsGsonPackageAccessor.java b/core/src/main/java/com/google/gson/JcloudsGsonPackageAccessor.java
deleted file mode 100644
index b7fd52655a..0000000000
--- a/core/src/main/java/com/google/gson/JcloudsGsonPackageAccessor.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- *
- * Copyright (C) 2011 Cloud Conscious, LLC.
- *
- * ====================================================================
- * 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;
-
-/**
- * handles the limitation in gson 1.6 where
- * {@link GsonBuilder#registerTypeHierarchyAdapter(Class, Object)} is package private.
- *
- * @see gson issue 271
- * @author Adrian Cole
- */
-public class JcloudsGsonPackageAccessor {
- public static GsonBuilder registerTypeHierarchyAdapter(GsonBuilder builder, Class> baseType, Object typeAdapter) {
- return builder.registerTypeHierarchyAdapter(baseType, typeAdapter);
- }
-}
diff --git a/core/src/main/java/com/google/gson/JsonLiteral.java b/core/src/main/java/com/google/gson/JsonLiteral.java
index bef99b7ea7..e3cb87bc02 100644
--- a/core/src/main/java/com/google/gson/JsonLiteral.java
+++ b/core/src/main/java/com/google/gson/JsonLiteral.java
@@ -23,11 +23,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
/**
- * The gson project use package to control access to their objects. However,
- * this prevents us from doing valid work, like controling the json emitted on a
- * per-object basis. This is here to afford us to do this.
+ * The gson project use package to control access to their objects. However, this prevents us from
+ * doing valid work, like controling the json emitted on a per-object basis. This is here to afford
+ * us to do this.
*
* @author Adrian Cole
+ * @see
*/
public final class JsonLiteral extends JsonElement {
private final CharSequence literal;
diff --git a/core/src/main/java/com/google/gson/MapTypeAdapter.java b/core/src/main/java/com/google/gson/MapTypeAdapter.java
deleted file mode 100644
index cfab58edc9..0000000000
--- a/core/src/main/java/com/google/gson/MapTypeAdapter.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- *
- * Copyright (C) 2011 Cloud Conscious, LLC.
- *
- * ====================================================================
- * 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;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.jclouds.json.internal.ParseObjectFromElement;
-
-@SuppressWarnings({ "unchecked", "rawtypes" })
-public class MapTypeAdapter implements JsonSerializer, JsonDeserializer, InstanceCreator {
-
- public JsonElement serialize(Map src, Type typeOfSrc, JsonSerializationContext context) {
- JsonObject map = new JsonObject();
- Type childGenericType = null;
- if (typeOfSrc instanceof ParameterizedType) {
- childGenericType = new TypeInfoMap(typeOfSrc).getValueType();
- }
-
- for (Map.Entry entry : (Set) src.entrySet()) {
- Object value = entry.getValue();
-
- JsonElement valueElement;
- if (value == null) {
- valueElement = JsonNull.createJsonNull();
- } else {
- Type childType = (childGenericType == null) ? value.getClass() : childGenericType;
- valueElement = context.serialize(value, childType);
- }
- map.add(String.valueOf(entry.getKey()), valueElement);
- }
- return map;
- }
-
- public Map deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
- // Use ObjectConstructor to create instance instead of hard-coding a specific type.
- // This handles cases where users are using their own subclass of Map.
- Map map = constructMapType(typeOfT, context);
- TypeInfoMap mapTypeInfo = new TypeInfoMap(typeOfT);
- for (Map.Entry entry : json.getAsJsonObject().entrySet()) {
- Object key = context.deserialize(new JsonPrimitive(entry.getKey()), mapTypeInfo.getKeyType());
- // START JCLOUDS PATCH
- Object value = null;
- if (mapTypeInfo.getValueType() == Object.class) {
- value = ParseObjectFromElement.SINGLETON.apply(entry.getValue());
- }
- if (value == null) {
- value = context.deserialize(entry.getValue(), mapTypeInfo.getValueType());
- }
- // END JCLOUDS PATCH
- map.put(key, value);
- }
- return map;
- }
-
- private Map constructMapType(Type mapType, JsonDeserializationContext context) {
- JsonDeserializationContextDefault contextImpl = (JsonDeserializationContextDefault) context;
- ObjectConstructor objectConstructor = contextImpl.getObjectConstructor();
- return (Map) objectConstructor.construct(mapType);
- }
-
- public Map createInstance(Type type) {
- return new LinkedHashMap();
- }
-
- @Override
- public String toString() {
- return MapTypeAdapter.class.getSimpleName();
- }
-}
\ No newline at end of file
diff --git a/core/src/main/java/com/google/gson/ObjectMapTypeAdapter.java b/core/src/main/java/com/google/gson/ObjectMapTypeAdapter.java
new file mode 100644
index 0000000000..ed91ae86ee
--- /dev/null
+++ b/core/src/main/java/com/google/gson/ObjectMapTypeAdapter.java
@@ -0,0 +1,90 @@
+/*
+ * 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;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.Set;
+
+import org.jclouds.json.internal.ParseObjectFromElement;
+
+import com.google.gson.internal.$Gson$Types;
+
+/**
+ * Default serialization and deserialization of a map type. This implementation really only works
+ * well with simple primitive types as the map key. If the key is not a simple primitive then the
+ * object is {@code toString}ed and that value is used as its key.
+ *
+ * Patched depending on this
+ * @author Joel Leitch
+ */
+@SuppressWarnings("unchecked")
+public final class ObjectMapTypeAdapter extends BaseMapTypeAdapter {
+
+ public JsonElement serialize(Map src, Type typeOfSrc, JsonSerializationContext context) {
+ JsonObject map = new JsonObject();
+ Type childGenericType = null;
+ if (typeOfSrc instanceof ParameterizedType) {
+ Class> rawTypeOfSrc = $Gson$Types.getRawType(typeOfSrc);
+ childGenericType = $Gson$Types.getMapKeyAndValueTypes(typeOfSrc, rawTypeOfSrc)[1];
+ }
+
+ for (Map.Entry entry : (Set) src.entrySet()) {
+ Object value = entry.getValue();
+
+ JsonElement valueElement;
+ if (value == null) {
+ valueElement = JsonNull.createJsonNull();
+ } else {
+ Type childType = (childGenericType == null)
+ ? value.getClass() : childGenericType;
+ valueElement = serialize(context, value, childType);
+ }
+ map.add(String.valueOf(entry.getKey()), valueElement);
+ }
+ return map;
+ }
+
+ public Map deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ throws JsonParseException {
+ // Use ObjectConstructor to create instance instead of hard-coding a specific type.
+ // This handles cases where users are using their own subclass of Map.
+ Map map = constructMapType(typeOfT, context);
+ Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(typeOfT, $Gson$Types.getRawType(typeOfT));
+ for (Map.Entry entry : json.getAsJsonObject().entrySet()) {
+ Object key = context.deserialize(new JsonPrimitive(entry.getKey()), keyAndValueTypes[0]);
+ // START JCLOUDS PATCH
+ // http://code.google.com/p/google-gson/issues/detail?id=325
+ Object value = null;
+ if (keyAndValueTypes[1] == Object.class) {
+ value = ParseObjectFromElement.SINGLETON.apply(entry.getValue());
+ }
+ if (value == null) {
+ value = context.deserialize(entry.getValue(), keyAndValueTypes[1]);
+ }
+ // END JCLOUDS PATCH
+ map.put(key, value);
+ }
+ return map;
+ }
+
+ @Override
+ public String toString() {
+ return MapTypeAdapter.class.getSimpleName();
+ }
+}
\ No newline at end of file
diff --git a/core/src/main/java/com/google/gson/Streams.java b/core/src/main/java/com/google/gson/Streams.java
index 24e2167553..c6b05f89bf 100644
--- a/core/src/main/java/com/google/gson/Streams.java
+++ b/core/src/main/java/com/google/gson/Streams.java
@@ -1,8 +1,6 @@
-/**
+/*
+ * Copyright (C) 2010 Google Inc.
*
- * Copyright (C) 2011 Cloud Conscious, LLC.
- *
- * ====================================================================
* 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
@@ -14,8 +12,8 @@
* 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;
import com.google.gson.stream.JsonReader;
@@ -104,7 +102,8 @@ final class Streams {
if (serializeNulls) {
writer.nullValue();
}
-//BEGIN JCLOUDS PATCH
+ //BEGIN JCLOUDS PATCH
+ // * @see
} else if (element instanceof JsonLiteral ) {
writer.value(JsonLiteral.class.cast(element));
//END JCLOUDS PATCH
diff --git a/core/src/main/java/com/google/gson/stream/JsonWriter.java b/core/src/main/java/com/google/gson/stream/JsonWriter.java
index bd01290581..bcf12bac95 100644
--- a/core/src/main/java/com/google/gson/stream/JsonWriter.java
+++ b/core/src/main/java/com/google/gson/stream/JsonWriter.java
@@ -1,21 +1,19 @@
-/**
+/*
+ * Copyright (C) 2010 Google Inc.
*
- * Copyright (C) 2011 Cloud Conscious, LLC.
- *
- * ====================================================================
* 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
+ * 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.stream;
import java.io.Closeable;
@@ -344,7 +342,7 @@ public final class JsonWriter implements Closeable {
return this;
}
//BEGIN JCLOUDS PATCH
-
+// * @see
/**
* Writes {@code value} literally
*
@@ -356,7 +354,6 @@ public final class JsonWriter implements Closeable {
return this;
}
//END JCLOUDS PATCH
-
/**
* Encodes {@code value}.
*
diff --git a/core/src/main/java/org/jclouds/domain/JsonBall.java b/core/src/main/java/org/jclouds/domain/JsonBall.java
index 227d5797d3..b5f524ad48 100644
--- a/core/src/main/java/org/jclouds/domain/JsonBall.java
+++ b/core/src/main/java/org/jclouds/domain/JsonBall.java
@@ -27,6 +27,7 @@ import org.jclouds.util.Patterns;
* As String is final, using a different marker to imply this is a json object
*
* @author Adrian Cole
+ * @see
*/
public class JsonBall implements java.io.Serializable, Comparable, CharSequence {
diff --git a/core/src/main/java/org/jclouds/json/config/GsonModule.java b/core/src/main/java/org/jclouds/json/config/GsonModule.java
index 1760798702..c56ff1e4d1 100644
--- a/core/src/main/java/org/jclouds/json/config/GsonModule.java
+++ b/core/src/main/java/org/jclouds/json/config/GsonModule.java
@@ -33,11 +33,12 @@ import org.jclouds.json.Json;
import org.jclouds.json.internal.EnumTypeAdapterThatReturnsFromValue;
import org.jclouds.json.internal.GsonWrapper;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
+import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.primitives.Bytes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import com.google.gson.JcloudsGsonPackageAccessor;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
@@ -46,7 +47,7 @@ import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
-import com.google.gson.MapTypeAdapter;
+import com.google.gson.ObjectMapTypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.inject.AbstractModule;
import com.google.inject.ImplementedBy;
@@ -63,11 +64,11 @@ public class GsonModule extends AbstractModule {
@Provides
@Singleton
Gson provideGson(JsonBallAdapter jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
- ByteArrayAdapter byteArrayAdapter, JsonAdapterBindings bindings) throws ClassNotFoundException, Exception {
+ ByteArrayAdapter byteArrayAdapter, SerializePropertiesDefaults propertiesAdapter,
+ JsonAdapterBindings bindings) throws ClassNotFoundException, Exception {
GsonBuilder builder = new GsonBuilder();
- JcloudsGsonPackageAccessor.registerTypeHierarchyAdapter(builder, Enum.class,
- new EnumTypeAdapterThatReturnsFromValue());
- JcloudsGsonPackageAccessor.registerTypeHierarchyAdapter(builder, Map.class, new MapTypeAdapter());
+ builder.registerTypeHierarchyAdapter(Enum.class, new EnumTypeAdapterThatReturnsFromValue());
+ builder.registerTypeHierarchyAdapter(Map.class, new ObjectMapTypeAdapter());
builder.registerTypeAdapter(JsonBall.class, jsonAdapter);
builder.registerTypeAdapter(Date.class, adapter);
builder.registerTypeAdapter(new TypeToken>() {
@@ -79,6 +80,7 @@ public class GsonModule extends AbstractModule {
return builder.create();
}
+ // http://code.google.com/p/google-gson/issues/detail?id=326
@ImplementedBy(JsonBallAdapterImpl.class)
public static interface JsonBallAdapter extends JsonSerializer, JsonDeserializer {
@@ -92,7 +94,7 @@ public class GsonModule extends AbstractModule {
}
public JsonBall deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
- throws JsonParseException {
+ throws JsonParseException {
return new JsonBall(json.toString());
}
@@ -118,7 +120,7 @@ public class GsonModule extends AbstractModule {
@Override
public List deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
- throws JsonParseException {
+ throws JsonParseException {
return Bytes.asList(CryptoStreams.hex(json.getAsString()));
}
@@ -134,7 +136,7 @@ public class GsonModule extends AbstractModule {
@Override
public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
- throws JsonParseException {
+ throws JsonParseException {
return CryptoStreams.hex(json.getAsString());
}
@@ -158,7 +160,7 @@ public class GsonModule extends AbstractModule {
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
- throws JsonParseException {
+ throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString();
try {
return dateService.iso8601DateParse(toParse);
@@ -183,7 +185,7 @@ public class GsonModule extends AbstractModule {
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
- throws JsonParseException {
+ throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString();
Date toReturn = dateService.cDateParse(toParse);
return toReturn;
@@ -199,7 +201,7 @@ public class GsonModule extends AbstractModule {
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
- throws JsonParseException {
+ throws JsonParseException {
long toParse = json.getAsJsonPrimitive().getAsLong();
if (toParse == -1)
return null;
diff --git a/core/src/main/java/org/jclouds/json/internal/JsonObjectAsMap.java b/core/src/main/java/org/jclouds/json/internal/JsonObjectAsMap.java
index c25969dc6a..f307da024f 100644
--- a/core/src/main/java/org/jclouds/json/internal/JsonObjectAsMap.java
+++ b/core/src/main/java/org/jclouds/json/internal/JsonObjectAsMap.java
@@ -27,7 +27,7 @@ import com.google.gson.JsonObject;
/**
* Exposes the JsonObject as a map so that we can use gauva apis on it.
- *
+ * http://code.google.com/p/google-gson/issues/detail?id=325
* @author Adrian Cole
*/
public enum JsonObjectAsMap implements Function> {
diff --git a/core/src/main/java/org/jclouds/json/internal/ParseObjectFromElement.java b/core/src/main/java/org/jclouds/json/internal/ParseObjectFromElement.java
index ed3a293b97..8aa5ca8ca2 100644
--- a/core/src/main/java/org/jclouds/json/internal/ParseObjectFromElement.java
+++ b/core/src/main/java/org/jclouds/json/internal/ParseObjectFromElement.java
@@ -24,12 +24,11 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
-import com.google.gson.MapTypeAdapter;
/**
* This is a class that helps the default {@link MapTypeAdapter} make a sane object graph when the
* value is set to {@code Object}
- *
+ * http://code.google.com/p/google-gson/issues/detail?id=325
* @author Adrian Cole
*/
public enum ParseObjectFromElement implements Function {
diff --git a/core/src/test/java/org/jclouds/json/JsonTest.java b/core/src/test/java/org/jclouds/json/JsonTest.java
index 5b7d8bcb49..0dea4e9e2a 100644
--- a/core/src/test/java/org/jclouds/json/JsonTest.java
+++ b/core/src/test/java/org/jclouds/json/JsonTest.java
@@ -36,6 +36,52 @@ import com.google.inject.TypeLiteral;
public class JsonTest {
private Json json = Guice.createInjector(new GsonModule()).getInstance(Json.class);
+ private static class ObjectNoDefaultConstructor {
+ private final String stringValue;
+ private final int intValue;
+
+ public ObjectNoDefaultConstructor(String stringValue, int intValue) {
+ this.stringValue = stringValue;
+ this.intValue = intValue;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + intValue;
+ 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;
+ ObjectNoDefaultConstructor other = (ObjectNoDefaultConstructor) obj;
+ if (intValue != other.intValue)
+ return false;
+ if (stringValue == null) {
+ if (other.stringValue != null)
+ return false;
+ } else if (!stringValue.equals(other.stringValue))
+ return false;
+ return true;
+ }
+ }
+
+ public void testObjectNoDefaultConstructor() {
+ ObjectNoDefaultConstructor obj = new ObjectNoDefaultConstructor("foo", 1);
+ assertEquals(json.toJson(obj), "{\"stringValue\":\"foo\",\"intValue\":1}");
+ ObjectNoDefaultConstructor obj2 = json.fromJson(json.toJson(obj), ObjectNoDefaultConstructor.class);
+ assertEquals(obj2, obj);
+ assertEquals(json.toJson(obj2), json.toJson(obj));
+ }
+
private static class EnumInside {
private static enum Test {
FOO, BAR;
@@ -52,7 +98,7 @@ public class JsonTest {
map.put("map", ImmutableMap.of("key", "value"));
map.put("list", ImmutableList.of("key", "value"));
assertEquals(json.toJson(map),
- "{\"string\":\"string\",\"map\":{\"key\":\"value\"},\"list\":[\"key\",\"value\"],\"boolean\":true,\"number\":1}");
+ "{\"string\":\"string\",\"map\":{\"key\":\"value\"},\"list\":[\"key\",\"value\"],\"boolean\":true,\"number\":1}");
Map map2 = json.fromJson(json.toJson(map), new TypeLiteral>() {
}.getType());
assertEquals(map2, map);
@@ -107,12 +153,12 @@ public class JsonTest {
public void testDeserializeEnumWithParser() {
assertEquals(json.fromJson("{enumValue : \"FOO\"}", EnumInsideWithParser.class).enumValue,
- EnumInsideWithParser.Test.FOO);
+ EnumInsideWithParser.Test.FOO);
}
public void testDeserializeEnumWithParserAndBadValue() {
assertEquals(json.fromJson("{enumValue : \"sd\"}", EnumInsideWithParser.class).enumValue,
- EnumInsideWithParser.Test.UNRECOGNIZED);
+ EnumInsideWithParser.Test.UNRECOGNIZED);
}
}