How to save default values ​​for a field in a deserialized object?

My situation is this: Object TableC has 4 fields. Only 3 fields ( field_C1 , field_C2 and field_C3 ) are read from the JSON string. The fourth field field_C4 defined inside the object with a default value.

When I serialize an instance of an object (for output) - it ignores the field_C4 field, I was expecting a default value of "1" or "null" . When I explicitly define the value for the instance field in the program for "NEW" , it includes it in the Json output line.

Looking at the output, it looks like the constructor is also ignored when an instance of the object is created during deserialization.

What would be the best way to activate other fields for an instance of an object - which are not included in the deserialized version of Json String input?

 package newpackage; import java.util.List; import com.google.gson.*; public class jsonwithconstructor { public static void main(String[] args) throws ClassNotFoundException { String jsonstring = "{'TableC':[" + "{'field_C1':'C_11','field_C2':'C_12','field_C3':'C_13'}," + "{'field_C1':'C_21','field_C2':'C_22','field_C3':'C_23'}" + "]}"; jsonstring = jsonstring.replace('\'', '"'); System.out.println(jsonstring); RootObject root = new GsonBuilder().create().fromJson(jsonstring, RootObject.class); for (int i=0; i < root.TableC.size(); i++){ System.out.println(root.TableC.get(i)); } System.out.println(); //root.TableC.get(0).field_C4 = "NEW"; for (int i=0; i < root.TableC.size(); i++){ System.out.println(root.TableC.get(i)); } System.out.println(); Gson gson = new Gson(); String jsonoutput = gson.toJson(root); System.out.println(jsonoutput); } public class TableC{ public String field_C1; public String field_C2; public String field_C3; public String field_C4 = "1"; public TableC(){ this.field_C4 = "1"; } @Override public String toString() { return ("TableC" + ", " + this.field_C1 + ", " + this.field_C2 + ", " + this.field_C3 + ", " + this.field_C4); } } public class RootObject{ public List<TableC> TableC; } } 

The result is shown below:

 {"TableC":[{"field_C1":"C_11","field_C2":"C_12","field_C3":"C_13"},{"field_C1":"C_21","field_C2":"C_22","field_C3":"C_23"}]} TableC, C_11, C_12, C_13, null TableC, C_21, C_22, C_23, null TableC, C_11, C_12, C_13, NEW TableC, C_21, C_22, C_23, null {"TableC":[{"field_C1":"C_11","field_C2":"C_12","field_C3":"C_13","field_C4":"NEW"},{"field_C1":"C_21","field_C2":"C_22","field_C3":"C_23"}]} 
+6
source share
3 answers

This is a known, currently open issue: https://github.com/google/gson/issues/513

Gson creates field values ​​in deserialized objects with reflection, so it sets values ​​based on what is only in JSON. Until Google provides fixes for this problem, you cannot do this.

There are several workarounds between you:

  • Wrap the fields in the getters and lazily load value. This is a good way (and my personal recommendation) to do this if the field is never allowed to be null , but they should be mutable.
  • Mark the default fields as final . This is a good way to do this if they are immutable.
  • Create a custom ExclusionStrategy and check the specific fields that should be ignored with FieldAttributes
    • This is the most versatile option, but also the code itself.
  • Deserialize your POJO using only those fields that do not exist, and then compose this data structure with a new one that has default values.

I agree that they all have flaws, but as I said above, this is an open issue with Gson.

+2
source

Using Gson v2.7, I see that it calls the default constructor of the deserialized object and any value initialized inside that is saved. However, I used "new Gson ()" instead of "GsonBuilder" if that matters.

+1
source

I am currently using this approach on v2.8.5:

 public class Test { @SerializedName("f") private int foo; @SerializedName("b") private int bar; public Test() { bar = -1; // Uses -1 as default value for bar variable when it not present in the JSON } ... } 

And parse it like:

 Test test = new GsonBuilder().create().fromJson(jsonString, Test.class); 
0
source

All Articles