【问题标题】:Can I apply a custom deserializer to within another custom deserializer for GSON我可以将自定义解串器应用到 GSON 的另一个自定义解串器中吗
【发布时间】:2016-09-23 15:01:50
【问题描述】:

以下是有助于在 Object 中相应转换 JSON 的工作代码。如果String为nil,则视为null。

有 2 个自定义解串器,即 MyOwnStringDeserializerMyOwnListDeserializer。我对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;
    }
}

【问题讨论】:

  • 错了,伙计!开玩笑地说:“有 2 个自定义反序列化器,即 MyOwnListDeserializerMyOwnListDeserializer。我对 MyOwnListDeserializer 不满意”嗯……你对哪个 MyOwnListDeserializer 不满意,第一个还是第二个?
  • 保持最小化 - 删除不必要的代码。 hashCode 和 equals 对您提出的问题没有任何帮助。试着打破你的线条,这样你就不需要 hscroll 来查看它了。
  • 谢谢阿德里安。修正了错字。没错,hashCode 和 equals 与问题无关。但是没有它,它就不能用于(测试的)比较......我提供了完整的代码,这样你就可以复制粘贴来尝试一下。

标签: java json gson deserialization json-deserialization


【解决方案1】:

您要查找的方法是JsonDeserializationContext.deserialize()。根据有关如何导致无限循环的警告,这会调用您设置的任何相关自定义反序列化器。

我相信用单行 MySubItems subItems = context.deserialize(element, MySubItems.class); 替换循环内的 subItems 的初始化可以解决问题,只留下循环体中的 list.add(subItems) 周围的检查。

【讨论】:

  • 效果很好。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-24
相关资源
最近更新 更多