2016-09-23 21 views
0

我有一个类MySimpleObject有不同的成员字段。给定一个JSON,它将相应地填充该字段。但是,如果json声明为“无”,我打算将其设置为null而不是字符串“nil”。如何为一个类的所有字段编写通用定制GSON解串器?

下面的例子应该是一个MySimpleObject,它的所有字段为null,长度为0的列表为subItemListmyObj1应该等于myObj2

@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); 
    } 
} 

如何编写自定义序列化程序而不必遍历每个jsonObject并检查“无”设置为空?

回答

1

我看着Gson库和gson-fire project,但他们都没有考虑到真正的通用(和高性能)解决方案。

一种方法是在将json字符串传递给gson对象之前,系统地将"nil"替换为"null"。它不是很干净,但它性能很好,可以工作。

这是一个基本的方法(一定要精):

public static String convertNil(String json){ 
     return json.replaceAll(":\\s*\"nil\"", ": null"); 
} 

然后使用它像:

MySimpleObject myObj1 = gson.fromJson(convertNil(myJson1), MySimpleObject.class); 
MySimpleObject myObj2 = gson.fromJson(convertNil(myJson2), MySimpleObject.class); 
+0

由于被发现。我喜欢你的思维答案。我的问题以前不是很正确。我修改了它。你可以检查你现在是否可以得到答案吗?谢谢!! – Elye

+0

我试过你的答案,它也给出了很好的结果。我赞成它。谢谢! – Elye

0

我设法拿出来完成这项工作,如下一些自定义的反序列化。

@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; 
    } 
} 

我仍然不是很高兴MyOwnListDeserializer,具有手动处理的SubItem1和subItem2,尽管他们应该有相同的规则由MyOwnStringDeserializer定义。但我只是不知道如何申请MyOwnStringDeserializerMyOwnListDeserializer

对于比我的其他更好的答案,我仍然可以开放。

更新更优化的答案可以在 https://stackoverflow.com/a/39671580/3286489

相关问题