Java Gson 仅在不为空或不为空时才序列化字段
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18491733/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Gson Serialize field only if not null or not empty
提问by zdesam
I have requirement where I need to convert java object to json.
我有需要将 java 对象转换为 json 的要求。
I am using Gson for that but i need the converter to only serialize the non null or not empty values.
我为此使用 Gson,但我需要转换器仅序列化非空值或非空值。
For example:
例如:
//my java object looks like
class TestObject{
String test1;
String test2;
OtherObject otherObject = new OtherObject();
}
now my Gson instance to convert this object to json looks like
现在我的 Gson 实例将此对象转换为 json 看起来像
Gson gson = new Gson();
TestObject obj = new TestObject();
obj.test1 = "test1";
obj.test2 = "";
String jsonStr = gson.toJson(obj);
println jsonStr;
In the above print, the result is
在上面的打印中,结果是
{"test1":"test1", "test2":"", "otherObject":{}}
Here i just wanted the result to be
在这里,我只想结果是
{"test1":"test1"}
Since the test2 is empty and otherObject is empty, i don't want them to be serialized to json data.
由于 test2 为空而 otherObject 为空,我不希望它们被序列化为 json 数据。
Btw, I am using Groovy/Grails so if there is any plugin for this that would be good, if not any suggestion to customize the gson serialization class would be good.
顺便说一句,我正在使用 Groovy/Grails,所以如果有任何插件会很好,如果没有任何自定义 gson 序列化类的建议会很好。
采纳答案by Sotirios Delimanolis
Create your own TypeAdapter
创建自己的 TypeAdapter
public class MyTypeAdapter extends TypeAdapter<TestObject>() {
@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
}
}
You can then register it with Gson
.
然后,您可以使用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));
produces
产生
{"test1":"test1"}
The GsonBuilder
class has a bunch of methods to create your own serialization/deserialization strategies, register type adapters, and set other parameters.
该GsonBuilder
班有一堆的方法来创建自己的序列化/反序列化战略,注册类型的适配器,等参数进行设置。
Strings
is a Guava class. You can do your own check if you don't want that dependency.
Strings
是番石榴类。如果您不想要这种依赖,您可以自行检查。
回答by toto2
It seems to me the problem is not with gson. Gson correctly keeps track of the difference between null and an empty string. Are you sure you want to erase that distinction? Are you sure all classes that use TestObject don't care?
在我看来,问题不在于 gson。Gson 正确跟踪 null 和空字符串之间的差异。您确定要消除这种区别吗?您确定所有使用 TestObject 的类都不关心吗?
What you could do if you don't care about the difference is to change the empty strings to null within a TestObject before serializing it. Or better, make the setters in TestObject such that an empty string is set to null; that way you define rigidly within the class that an empty string is the same as null. You'll have to make sure the values cannot be set outside the setters.
如果您不关心差异,您可以做的是在序列化之前将 TestObject 中的空字符串更改为 null。或者更好的是,使 TestObject 中的 setter 将空字符串设置为 null;这样您就可以在类中严格定义空字符串与 null 相同。您必须确保不能在 setter 之外设置这些值。
回答by Stan
What I personally don't like in TypeAdapter
using answer is the fact you need to describe every field of your entire class which could have lets say 50 fields (which means 50 if
blocks in TypeAdapter
).
My solution is based on Reflection
and a fact Gson
will not serialize null values fields by default.
I have a special class which holds data for API to create document called DocumentModel, which has about 50 fields and I don't like to send String
fields with "" (empty but not null) values or empty arrays to server. So I created a special method which returns me a copy of my object with all empty fields nulled. Note - by default all arrays in my DocumentModel instance are initialized as empty (zero length) arrays and thus they are never null, you should probably check your arrays for null before checking their length.
我个人不喜欢TypeAdapter
使用答案的事实是,您需要描述整个班级的每个字段,这些字段可能有 50 个字段(这意味着 50if
个块TypeAdapter
)。
我的解决方案基于Reflection
并且Gson
默认情况下不会序列化空值字段。
我有一个特殊的类,它保存 API 的数据以创建名为 DocumentModel 的文档,它有大约 50 个字段,我不喜欢发送String
带有“”(空但不为空)值或空数组的字段到服务器。所以我创建了一个特殊的方法,它返回我的对象的副本,其中所有空字段都为空。注意 - 默认情况下,我的 DocumentModel 实例中的所有数组都初始化为空(零长度)数组,因此它们永远不会为空,您可能应该在检查数组长度之前检查数组是否为空。
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;
}
Using this method I don't care if some fields was added or removed after this method was written or whatever. The only problem left - is checking custom type fields, which are not String
or array, but this depends to particular class and should be extra coded in if/else blocks.
使用此方法,我不在乎在编写此方法后是否添加或删除了某些字段或其他内容。剩下的唯一问题是检查自定义类型字段,它们不是String
或数组,但这取决于特定的类,应该在 if/else 块中额外编码。