我可以将自定义反序列化器应用于 GSON 的另一个自定义反序列化器吗
Can I apply a custom deserializer to within another custom deserializer for GSON
下面是一个工作代码,有助于相应地在对象中转换 JSON。如果 String 是 nil
,它将被视为 null。
有 2 个自定义反序列化器,即 MyOwnStringDeserializer
和 MyOwnListDeserializer
。我对 MyOwnListDeserializer
反序列化器不满意,因为本质上它所做的是将字符串与 MyOwnStringDeserializer
中定义的规则进行比较。但我不能也不知道如何将 MyOwnStringDeserializer
应用到 MyOwnListDeserializer
.
有没有一种方法可以简化 MyOwnListDeserializer
?或者如果有一种方法可以只使用一个自定义反序列化器并且仍然可以获得相同的结果,那就更好了?
@Test
public void myTestFunction() {
String myJson1 = "{\"item1\":\"nil\",\"item2\":\"nil\",\"subItemList\":[{\"subItem1\":\"nil\",\"subItem2\":\"nil\"}]}";
String myJson2 = "{\"subItemList\":[]}";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(new TypeToken<List<MySubItems>>(){ }.getType(), new MyOwnListDeserializer());
gsonBuilder.registerTypeAdapter(String.class, new MyOwnStringDeserializer());
Gson gson = gsonBuilder.create();
MySimpleObject myObj1 = gson.fromJson(myJson1, MySimpleObject.class);
MySimpleObject myObj2 = gson.fromJson(myJson2, MySimpleObject.class);
assertThat(myObj1.equals((myObj2))).isTrue();
}
class MySimpleObject implements Serializable {
String item1 = null;
String item2 = null;
List<MySubItems> subItemList;
@Override
public int hashCode() {
int hash = 17;
hash = 31*hash + ((item1 == null)? 0 :item1.hashCode());
hash = 31*hash + ((item2 == null)? 0 :item2.hashCode());
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MySimpleObject) {
return this.hashCode() == obj.hashCode();
}
return super.equals(obj);
}
}
class MySubItems implements Serializable {
String subItem1 = null;
String subItem2 = null;
@Override
public int hashCode() {
int hash = 17;
hash = 31*hash + ((subItem1 == null)? 0 :subItem1.hashCode());
hash = 31*hash + ((subItem2 == null)? 0 :subItem2.hashCode());
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MySubItems) {
return this.hashCode() == obj.hashCode();
}
return super.equals(obj);
}
}
class MyOwnStringDeserializer implements JsonDeserializer<String> {
@Override
public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return (json.getAsString().equals("nil"))? null : json.getAsString();
}
}
class MyOwnListDeserializer implements JsonDeserializer<List<MySubItems>> {
@Override
public List<MySubItems> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
List<MySubItems> list = new ArrayList<>();
for (JsonElement element : json.getAsJsonArray()) {
JsonObject subObj = element.getAsJsonObject();
MySubItems subItems = new MySubItems();
if (!subObj.get("subItem1").getAsString().equals("nil")) {
subItems.subItem1 = subObj.get("subItem1").getAsString();
}
if (!subObj.get("subItem2").getAsString().equals("nil")) {
subItems.subItem2 = subObj.get("subItem1").getAsString();
}
if (subItems.subItem1 != null || subItems.subItem2 != null) {
list.add(subItems);
}
}
return (list.size() == 0)? null : list;
}
}
您要找的方法是JsonDeserializationContext.deserialize()
。根据有关如何导致无限循环的警告,这会调用您设置的任何相关自定义反序列化器。
我相信用单行 MySubItems subItems = context.deserialize(element, MySubItems.class);
替换循环内 subItems
的初始化就可以解决问题,只留下它和循环体中 list.add(subItems)
周围的检查.
下面是一个工作代码,有助于相应地在对象中转换 JSON。如果 String 是 nil
,它将被视为 null。
有 2 个自定义反序列化器,即 MyOwnStringDeserializer
和 MyOwnListDeserializer
。我对 MyOwnListDeserializer
反序列化器不满意,因为本质上它所做的是将字符串与 MyOwnStringDeserializer
中定义的规则进行比较。但我不能也不知道如何将 MyOwnStringDeserializer
应用到 MyOwnListDeserializer
.
有没有一种方法可以简化 MyOwnListDeserializer
?或者如果有一种方法可以只使用一个自定义反序列化器并且仍然可以获得相同的结果,那就更好了?
@Test
public void myTestFunction() {
String myJson1 = "{\"item1\":\"nil\",\"item2\":\"nil\",\"subItemList\":[{\"subItem1\":\"nil\",\"subItem2\":\"nil\"}]}";
String myJson2 = "{\"subItemList\":[]}";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(new TypeToken<List<MySubItems>>(){ }.getType(), new MyOwnListDeserializer());
gsonBuilder.registerTypeAdapter(String.class, new MyOwnStringDeserializer());
Gson gson = gsonBuilder.create();
MySimpleObject myObj1 = gson.fromJson(myJson1, MySimpleObject.class);
MySimpleObject myObj2 = gson.fromJson(myJson2, MySimpleObject.class);
assertThat(myObj1.equals((myObj2))).isTrue();
}
class MySimpleObject implements Serializable {
String item1 = null;
String item2 = null;
List<MySubItems> subItemList;
@Override
public int hashCode() {
int hash = 17;
hash = 31*hash + ((item1 == null)? 0 :item1.hashCode());
hash = 31*hash + ((item2 == null)? 0 :item2.hashCode());
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MySimpleObject) {
return this.hashCode() == obj.hashCode();
}
return super.equals(obj);
}
}
class MySubItems implements Serializable {
String subItem1 = null;
String subItem2 = null;
@Override
public int hashCode() {
int hash = 17;
hash = 31*hash + ((subItem1 == null)? 0 :subItem1.hashCode());
hash = 31*hash + ((subItem2 == null)? 0 :subItem2.hashCode());
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MySubItems) {
return this.hashCode() == obj.hashCode();
}
return super.equals(obj);
}
}
class MyOwnStringDeserializer implements JsonDeserializer<String> {
@Override
public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return (json.getAsString().equals("nil"))? null : json.getAsString();
}
}
class MyOwnListDeserializer implements JsonDeserializer<List<MySubItems>> {
@Override
public List<MySubItems> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
List<MySubItems> list = new ArrayList<>();
for (JsonElement element : json.getAsJsonArray()) {
JsonObject subObj = element.getAsJsonObject();
MySubItems subItems = new MySubItems();
if (!subObj.get("subItem1").getAsString().equals("nil")) {
subItems.subItem1 = subObj.get("subItem1").getAsString();
}
if (!subObj.get("subItem2").getAsString().equals("nil")) {
subItems.subItem2 = subObj.get("subItem1").getAsString();
}
if (subItems.subItem1 != null || subItems.subItem2 != null) {
list.add(subItems);
}
}
return (list.size() == 0)? null : list;
}
}
您要找的方法是JsonDeserializationContext.deserialize()
。根据有关如何导致无限循环的警告,这会调用您设置的任何相关自定义反序列化器。
我相信用单行 MySubItems subItems = context.deserialize(element, MySubItems.class);
替换循环内 subItems
的初始化就可以解决问题,只留下它和循环体中 list.add(subItems)
周围的检查.