Issue 797: gson 2+ addresses gson issue 325

This commit is contained in:
Adrian Cole 2012-01-01 15:47:48 -08:00
parent 92a926d655
commit 82c1d11191
4 changed files with 0 additions and 209 deletions

View File

@ -1,92 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package 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.
* <p/>
* Patched depending on <a href="http://code.google.com/p/google-gson/issues/detail?id=325">this</a>
* @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<Map.Entry>) 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<Object, Object> map = constructMapType(typeOfT, context);
Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(typeOfT, $Gson$Types.getRawType(typeOfT));
for (Map.Entry<String, JsonElement> 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();
}
}

View File

@ -51,7 +51,6 @@ import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.ObjectMapTypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.inject.AbstractModule;
import com.google.inject.ImplementedBy;
@ -74,7 +73,6 @@ public class GsonModule extends AbstractModule {
GsonBuilder builder = new GsonBuilder();
Logger.getLogger("com.google.gson.ParameterizedTypeHandlerMap").setLevel(Level.OFF);
builder.registerTypeHierarchyAdapter(Enum.class, new EnumTypeAdapterThatReturnsFromValue());
builder.registerTypeHierarchyAdapter(Map.class, new ObjectMapTypeAdapter());
builder.registerTypeAdapter(JsonBall.class, jsonAdapter);
builder.registerTypeAdapter(Date.class, adapter);
builder.registerTypeAdapter(Properties.class, propertiesAdapter);

View File

@ -1,58 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.json.internal;
import java.lang.reflect.Field;
import java.util.Map;
import com.google.common.base.Function;
import com.google.gson.JsonElement;
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<JsonObject, Map<String, JsonElement>> {
INSTANCE;
private final Field members;
JsonObjectAsMap() {
try {
members = JsonObject.class.getDeclaredField("members");
members.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new UnsupportedOperationException("cannot access gson internals", e);
}
}
@SuppressWarnings("unchecked")
@Override
public Map<String, JsonElement> apply(JsonObject in) {
try {
return (Map<String, JsonElement>) members.get(in);
} catch (IllegalArgumentException e) {
throw new UnsupportedOperationException("cannot access gson internals", e);
} catch (IllegalAccessException e) {
throw new UnsupportedOperationException("cannot access gson internals", e);
}
}
}

View File

@ -1,57 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.json.internal;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
/**
* 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<JsonElement, Object> {
SINGLETON;
public Object apply(JsonElement input) {
Object value = null;
if (input == null || input.isJsonNull()) {
value = null;
} else if (input.isJsonPrimitive()) {
JsonPrimitive primitive = input.getAsJsonPrimitive();
if (primitive.isNumber()) {
value = primitive.getAsNumber();
} else if (primitive.isBoolean()) {
value = primitive.getAsBoolean();
} else {
value = primitive.getAsString();
}
} else if (input.isJsonArray()) {
value = Lists.newArrayList(Iterables.transform(input.getAsJsonArray(), this));
} else if (input.isJsonObject()) {
value = Maps.<String,Object>newLinkedHashMap(Maps.transformValues(JsonObjectAsMap.INSTANCE.apply(input.getAsJsonObject()),
this));
}
return value;
}
}