mirror of https://github.com/apache/jclouds.git
Fixed bug found in docker provider where deserialization constructors don't handle json null.
This commit is contained in:
parent
bfa91d5614
commit
efd2beb4c5
|
@ -166,7 +166,7 @@ public final class DeserializationConstructorAndReflectiveTypeAdapterFactory imp
|
||||||
empty = false;
|
empty = false;
|
||||||
String name = in.nextName();
|
String name = in.nextName();
|
||||||
ParameterReader<?> parameter = parameterReaders.get(name);
|
ParameterReader<?> parameter = parameterReaders.get(name);
|
||||||
if (parameter == null) {
|
if (parameter == null || in.peek() == JsonToken.NULL) {
|
||||||
in.skipValue();
|
in.skipValue();
|
||||||
} else {
|
} else {
|
||||||
Object value = parameter.read(in);
|
Object value = parameter.read(in);
|
||||||
|
|
|
@ -128,8 +128,8 @@ public class Reflection2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This gets all declared constructors, not just public ones. makes them accessible, as well.
|
* This gets all declared constructors or factory methods on abstract types, not just public ones, and makes them
|
||||||
* This also includes factory methods on abstract types, defined static methods returning the same type.
|
* accessible.
|
||||||
*/
|
*/
|
||||||
private static LoadingCache<TypeToken<?>, Set<Invokable<?, ?>>> constructorsForTypeToken = CacheBuilder
|
private static LoadingCache<TypeToken<?>, Set<Invokable<?, ?>>> constructorsForTypeToken = CacheBuilder
|
||||||
.newBuilder().build(new CacheLoader<TypeToken<?>, Set<Invokable<?, ?>>>() {
|
.newBuilder().build(new CacheLoader<TypeToken<?>, Set<Invokable<?, ?>>>() {
|
||||||
|
@ -143,6 +143,7 @@ public class Reflection2 {
|
||||||
if (Modifier.isAbstract(key.getRawType().getModifiers())) {
|
if (Modifier.isAbstract(key.getRawType().getModifiers())) {
|
||||||
for (Invokable<?, Object> method : methods(key.getRawType())){
|
for (Invokable<?, Object> method : methods(key.getRawType())){
|
||||||
if (method.isStatic() && method.getReturnType().equals(key)) {
|
if (method.isStatic() && method.getReturnType().equals(key)) {
|
||||||
|
method.setAccessible(true);
|
||||||
builder.add(method);
|
builder.add(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,17 @@ import static com.google.common.io.BaseEncoding.base16;
|
||||||
import static com.google.common.primitives.Bytes.asList;
|
import static com.google.common.primitives.Bytes.asList;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.json.config.GsonModule;
|
import org.jclouds.json.config.GsonModule;
|
||||||
import org.jclouds.json.config.GsonModule.DefaultExclusionStrategy;
|
import org.jclouds.json.config.GsonModule.DefaultExclusionStrategy;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.gson.FieldAttributes;
|
import com.google.gson.FieldAttributes;
|
||||||
|
@ -210,67 +213,73 @@ public class JsonTest {
|
||||||
EnumInsideWithParser.Test.UNRECOGNIZED);
|
EnumInsideWithParser.Test.UNRECOGNIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract static class SpinalCasedType {
|
private abstract static class UpperCamelCasedType {
|
||||||
abstract String id();
|
abstract String id();
|
||||||
|
|
||||||
abstract String contentType();
|
@Nullable abstract Map<String, String> volumes();
|
||||||
|
|
||||||
// Currently, this only works for deserialization. Need to set a naming policy for serialization!
|
// Currently, this only works for deserialization. Need to set a naming policy for serialization!
|
||||||
@SerializedNames({ "id", "content-type" })
|
@SerializedNames({ "Id", "Volumes" })
|
||||||
private static SpinalCasedType create(String id, String contentType) {
|
private static UpperCamelCasedType create(String id, Map<String, String> volumes) {
|
||||||
return new SpinalCasedTypeImpl(id, contentType);
|
return new UpperCamelCasedTypeImpl(id, volumes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void spinalCaseWithSerializedNames() {
|
public void upperCamelCaseWithSerializedNames() {
|
||||||
Json json = Guice.createInjector(new GsonModule(), new AbstractModule() {
|
Json json = Guice.createInjector(new GsonModule(), new AbstractModule() {
|
||||||
@Override protected void configure() {
|
@Override protected void configure() {
|
||||||
bind(FieldNamingPolicy.class).toInstance(FieldNamingPolicy.LOWER_CASE_WITH_DASHES);
|
bind(FieldNamingPolicy.class).toInstance(FieldNamingPolicy.UPPER_CAMEL_CASE);
|
||||||
}
|
}
|
||||||
}).getInstance(Json.class);
|
}).getInstance(Json.class);
|
||||||
|
|
||||||
SpinalCasedType resource = SpinalCasedType.create("1234", "application/json");
|
UpperCamelCasedType resource = UpperCamelCasedType.create("1234", Collections.<String, String>emptyMap());
|
||||||
String spinalJson = "{\"id\":\"1234\",\"content-type\":\"application/json\"}";
|
String spinalJson = "{\"Id\":\"1234\",\"Volumes\":{}}";
|
||||||
|
|
||||||
assertEquals(json.toJson(resource), spinalJson);
|
assertEquals(json.toJson(resource), spinalJson);
|
||||||
assertEquals(spinalJson, json.toJson(resource));
|
assertEquals(json.fromJson(spinalJson, UpperCamelCasedType.class), resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SpinalCasedTypeImpl extends SpinalCasedType {
|
public void upperCamelCaseWithSerializedNamesNullJsonValue() {
|
||||||
private final String id;
|
Json json = Guice.createInjector(new GsonModule(), new AbstractModule() {
|
||||||
private final String contentType;
|
@Override protected void configure() {
|
||||||
|
bind(FieldNamingPolicy.class).toInstance(FieldNamingPolicy.UPPER_CAMEL_CASE);
|
||||||
|
}
|
||||||
|
}).getInstance(Json.class);
|
||||||
|
|
||||||
private SpinalCasedTypeImpl(String id, String contentType) {
|
assertEquals(json.fromJson("{\"Id\":\"1234\",\"Volumes\":null}", UpperCamelCasedType.class),
|
||||||
|
UpperCamelCasedType.create("1234", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class UpperCamelCasedTypeImpl extends UpperCamelCasedType {
|
||||||
|
private final String id;
|
||||||
|
private final Map<String, String> volumes;
|
||||||
|
|
||||||
|
private UpperCamelCasedTypeImpl(String id, Map<String, String> volumes) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.contentType = contentType;
|
this.volumes = volumes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override String id() {
|
@Override String id() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override String contentType() {
|
@Override @Nullable Map<String, String> volumes() {
|
||||||
return contentType;
|
return volumes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean equals(Object o) {
|
@Override public boolean equals(Object o) {
|
||||||
if (o == this) {
|
if (o == this) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (o instanceof SpinalCasedType) {
|
if (o instanceof UpperCamelCasedType) {
|
||||||
SpinalCasedType that = (SpinalCasedType) o;
|
UpperCamelCasedType that = (UpperCamelCasedType) o;
|
||||||
return (this.id.equals(that.id())) && (this.contentType.equals(that.contentType()));
|
return Objects.equal(this.id, that.id()) && Objects.equal(this.volumes, that.volumes());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int hashCode() {
|
@Override public int hashCode() {
|
||||||
int h = 1;
|
return Objects.hashCode(id, volumes);
|
||||||
h *= 1000003;
|
|
||||||
h ^= id.hashCode();
|
|
||||||
h *= 1000003;
|
|
||||||
h ^= contentType.hashCode();
|
|
||||||
return h;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue