Gson序列化字段仅在非空或非空时

我有需要将java对象转换为json。

我正在使用Gson,但我需要转换器只序列化非null或非空值。

例如:

//my java object looks like class TestObject{ String test1; String test2; OtherObject otherObject = new OtherObject(); } 

现在我的Gson实例将此对象转换为json看起来像

 Gson gson = new Gson(); TestObject obj = new TestObject(); obj.test1 = "test1"; obj.test2 = ""; String jsonStr = gson.toJson(obj); println jsonStr; 

在上面的印刷品中,结果是

 {"test1":"test1", "test2":"", "otherObject":{}} 

在这里,我只想要结果

 {"test1":"test1"} 

由于test2为空且otherObject为空,我不希望它们被序列化为json数据。

顺便说一句,我正在使用Groovy / Grails,所以如果有任何插件,这将是好的,如果没有任何建议自定义gson序列化类将是好的。

创建自己的TypeAdapter

 public class MyTypeAdapter extends TypeAdapter() { @Override public void write(JsonWriter out, TestObject value) throws IOException { out.beginObject(); if (!Strings.isNullOrEmpty(value.test1)) { out.name("test1"); out.value(value.test1); } if (!Strings.isNullOrEmpty(value.test2)) { out.name("test2"); out.value(value.test1); } /* similar check for otherObject */ out.endObject(); } @Override public TestObject read(JsonReader in) throws IOException { // do something similar, but the other way around } } 

然后你可以用Gson注册它。

 Gson gson = new GsonBuilder().registerTypeAdapter(TestObject.class, new MyTypeAdapter()).create(); TestObject obj = new TestObject(); obj.test1 = "test1"; obj.test2 = ""; System.out.println(gson.toJson(obj)); 

产生

  {"test1":"test1"} 

GsonBuilder类有一堆方法来创建自己的序列化/反序列化策略,寄存器类型适配器,以及设置其他参数。

Strings是番石榴类。 如果你不想要那种依赖,你可以自己检查。

我个人不喜欢在TypeAdapter使用答案的事实是你需要描述整个类的每个字段,这可以说50个字段(这意味着ifTypeAdapter有50个字段)。
我的解决方案基于Reflection和一个事实, Gson默认不会序列化空值字段。
我有一个特殊的类,它保存API的数据以创建名为DocumentModel的文档,该文档有大约50个字段,我不喜欢向服务器发送带有“”(空但不为空)值或空数组的String字段。 所以我创建了一个特殊的方法,它返回一个我的对象的副本,所有空字段都是空的。 注意 – 默认情况下,我的DocumentModel实例中的所有数组都被初始化为空(零长度)数组,因此它们永远不会为空,您应该在检查其长度之前检查数组是否为null。

 public DocumentModel getSerializableCopy() { Field fields[] = new Field[]{}; try { // returns the array of Field objects representing the public fields fields = DocumentModel.class.getDeclaredFields(); } catch (Exception e) { e.printStackTrace(); } DocumentModel copy = new DocumentModel(); Object value; for (Field field : fields) { try { value = field.get(this); if (value instanceof String && TextUtils.isEmpty((String) value)) { field.set(copy, null); // note: here array is not being checked for null! else if (value instanceof Object[] && ((Object[]) value).length == 0) { field.set(copy, null); } else field.set(copy, value); } catch (IllegalAccessException e) { e.printStackTrace(); } } return copy; } 

使用这种方法我不关心在写入此方法之后是否添加或删除了某些字段。 剩下的唯一问题是检查自定义类型字段,它们不是String或数组,但这取决于特定的类,应该在if / else块中进行额外编码。

在我看来问题不在于gson。 Gson正确地跟踪null和空字符串之间的差异。 你确定要删除这种区别吗? 您确定使用TestObject的所有类都不关心吗?

如果不关心差异,可以做的是在序列化之前将空字符串在TestObject中更改为null。 或者更好的是,在TestObject中创建setter,使空字符串设置为null; 这样你就可以在类中严格定义空字符串与null相同。 您必须确保不能在设置者之外设置值。