忍受我的英语。我有一个简单的json,
{
"Hint2": "L"
}
这是有效的POJO。
public class Hints {
@SerializedName("Hint2")
@Expose
private String Hint2;
public void setHint1(Object Hint2) {
this.Hint2 = (Hint2);
}
}
我想将其更改为
public class Hints {
@SerializedName("Hint2")
@Expose
public final ObservableField<String> Hint2 = new ObservableField<>();
public void setHint2(String Hint2) {
this.Hint2.set(Hint2);
}
}
两个类都有相同的setter方法,相同的@SerializedName注释标记。只更改了Hint2对象的类型。但后者抛出以下所示的异常
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at..
所以我相信反序列化取决于什么样的变量&#34; Hint2&#34;是。
有没有办法让它与ObservableField一起使用而不是使用String?
我尝试这个的原因是android绑定库,它支持将对象直接绑定到xml文件。当POJO中的相应值发生变化时,ObservableField会自动更新UI。
的更新
gson design document有此
使用字段与getter来指示Json元素
一些Json库使用类型的getter来推导出Json元素。我们选择使用非瞬态,静态或合成的所有字段(继承层次结构)。我们这样做是因为并非所有类都使用适当命名的getter编写。此外,getXXX或isXXX可能是语义而不是指示属性。
但是,也有很好的理由来支持物业。我们打算在后一版本中增强Gson以支持属性作为指示Json字段的备用映射。 目前,Gson是基于字段的。
所以这表明Gson是基于字段的。这几乎回答了我的问题,但仍在等待,如果有人对此有所了解。
答案 0 :(得分:1)
我遇到了相同的要求,并最终解决了,这里是步骤:
public class GsonUtils {
// code following
//...
}
以下代码在此类
中
private static class ObservableFieldSerializerDeserializer implements JsonSerializer>, JsonDeserializer> {
@Override
public JsonElement serialize(ObservableField src, Type typeOfSrc, JsonSerializationContext context) {
return context.serialize(src.get());
}
@Override
public ObservableField deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
final Type type = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
return new ObservableField((T) GsonUtils.getGson().fromJson(json, type));
}
}
private static GsonBuilder createGsonBuilder() {
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(new TypeToken<ObservableField<String>>(){}.getType(), new ObservableFieldSerializerDeserializer<String>());
...// register more types which are wrapped by ObservableFields
return gsonBuilder;
}
private static final Gson sGson = createGson();
private static Gson createGson() {
return createGsonBuilder().create();
}
// this is used by the deserializer
public static Gson getGson() {
return sGson;
}
这一切,希望有所帮助
答案 1 :(得分:0)
我刚刚遇到了我认为同样的问题,这是一个JUnit4测试,显示我是如何用Jackson解决它的POJO,但当然String也可以。
public class ObservableDeserializationTest {
private static class ObservableDeserializer extends JsonDeserializer<ObservableField> implements ContextualDeserializer {
private Class<?> mTargetClass;
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
mTargetClass = property.getType().containedType(0).getRawClass();
return this;
}
@Override
public ObservableField deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObservableField result = new ObservableField();
result.set(p.readValueAs(mTargetClass));
return result;
}
}
private static class SomePojo {
public String id;
public String name;
}
private static class ObservableTestClass {
@JsonDeserialize(using = ObservableDeserializer.class)
public ObservableField<SomePojo> testObj = new ObservableField<>();
}
@Test
public void DeserializingAnObservableObjectShouldSetValueCorrectly() {
ObservableTestClass tc = null;
try {
tc = new ObjectMapper().readValue("{\"testObj\":{\"name\":\"TestName\",\"id\":\"TestId\"}}", ObservableTestClass.class);
} catch (IOException e) {
e.printStackTrace();
}
Assert.assertEquals("TestName", tc.testObj.get().name);
Assert.assertEquals("TestId", tc.testObj.get().id);
}
}
关键是ContextualDeserializer接口,它允许提取包含的类类型。 Jackson提供了几种注册自定义反序列化器的选项,所以这只是一种方法。此外,如果您将其用于实数,那么在反序列化器中覆盖getNullValue可能是个好主意。