Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gson Serialize field only if not null or not empty

I have requirement where I need to convert java object to json.

I am using Gson for that but i need the converter to only serialize the non null or not empty values.

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 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.

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.

like image 759
zdesam Avatar asked Aug 28 '13 15:08

zdesam


People also ask

How do I ignore null in Gson?

The default behavior that is implemented in Gson is that null object fields are ignored. For example, if in Employee object, we do not specify the email (i.e. email is null ) then email will not be part of serialized JSON output. Gson ignores null fields because this behavior allows a more compact JSON output format.

How do you handle null in Gson?

By default, the Gson object does not serialize the fields with null values to JSON. If a field in a Java object is null, Gson excludes it. We can force Gson to serialize null values via the GsonBuilder class. We need to call the serializeNulls() method on the GsonBuilder instance before creating the Gson object.

Does Gson ignore unknown fields?

As you can see, Gson will ignore the unknown fields and simply match the fields that it's able to.

How do I ignore null values in JSON Request spring boot?

You can ignore null fields at the class level by using @JsonInclude(Include. NON_NULL) to only include non-null fields, thus excluding any attribute whose value is null. You can also use the same annotation at the field level to instruct Jackson to ignore that field while converting Java object to json if it's null.


2 Answers

Create your own 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 = 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.

Strings is a Guava class. You can do your own check if you don't want that dependency.

like image 131
Sotirios Delimanolis Avatar answered Sep 28 '22 00:09

Sotirios Delimanolis


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.

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.

like image 24
Stan Avatar answered Sep 28 '22 00:09

Stan