My situation is as follows: 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
is defined within the object with a default value.
我的情况如下:对象TableC有4个字段。仅从JSON字符串中读取3个字段(field_C1,field_C2和field_C3)。第四字段field_C4在对象内被定义为具有默认值。
When I serialize the object instance (for output) - it ignores the field field_C4
, I was expecting the default value of "1"
or "null"
. When I explicitly define a value to the instance-field within the program to "NEW"
, it does include it in the Json output string.
当我序列化对象实例(用于输出)时 - 它忽略字段field_C4,我期望默认值为“1”或“null”。当我明确地将程序中的实例字段的值定义为“NEW”时,它确实将它包含在Json输出字符串中。
Looking at the output, it looks as if the constructor is also ignored when the object instance is created during deserialization.
查看输出,在反序列化期间创建对象实例时,看起来好像也忽略了构造函数。
What would be the best practice to activate the other fields for the object instance - which are not included in the Deserialized version of the input Json String?
激活对象实例的其他字段的最佳做法是什么 - 它们未包含在输入Json String的反序列化版本中?
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 output 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"}]}
2 个解决方案
#1
2
This is a known, currently open issue: https://github.com/google/gson/issues/513
Gson constructs the values of fields in deserialized objects with reflection, so it will set the values based on what's in the JSON only. Until Google provides a fix for this issue, there isn't that much you can do.
Gson使用反射构*序列化对象中的字段值,因此它将仅根据JSON中的内容设置值。在Google为此问题提供修复程序之前,您无法做到这一点。
There are a number of workaround objects you have in the meantime:
在此期间,您有许多变通方法对象:
- Wrap the fields in getters, and lazily load the value. This is a good way (and my personal recommendation) to do it if a field is never ever allowed to be
null
, but they do need to be mutable. - 将字段包装在getter中,然后懒洋洋地加载值。如果永远不允许字段为空,这是一种很好的方式(以及我的个人建议),但它们确实需要是可变的。
- Mark the default fields as
final
. This a good way to do it if they are immutable. - 将默认字段标记为final。如果它们是不可变的,这是一个很好的方法。
- Create a custom
ExclusionStrategy
, and mark the particular fields that should be ignored usingFieldAttributes
- This is the most versatile of the options but also the most code.
- 这是最通用的选项,但也是最多的代码。
- 创建自定义ExclusionStrategy,并使用FieldAttributes标记应忽略的特定字段。这是最通用的选项,但也是最多的代码。
- Deserialize your POJO using just the fields that don't exist, and then compose that data structure with a new one that has the default values.
- 仅使用不存在的字段反序列化您的POJO,然后使用具有默认值的新数据组成该数据结构。
I agree that all of these have drawbacks, but as I said above, this is an open issue with Gson.
我同意所有这些都有缺点,但正如我上面所说,这是Gson的一个悬而未决的问题。
#2
1
Using Gson v2.7, I can see that it calls the default constructor of the deserialized object and any value initialized inside that is retained. However, I was using "new Gson()" instead of "GsonBuilder", if that makes any difference.
使用Gson v2.7,我可以看到它调用了反序列化对象的默认构造函数,并保留了内部初始化的任何值。但是,我使用的是“new Gson()”而不是“GsonBuilder”,如果这有任何区别的话。
#1
2
This is a known, currently open issue: https://github.com/google/gson/issues/513
Gson constructs the values of fields in deserialized objects with reflection, so it will set the values based on what's in the JSON only. Until Google provides a fix for this issue, there isn't that much you can do.
Gson使用反射构*序列化对象中的字段值,因此它将仅根据JSON中的内容设置值。在Google为此问题提供修复程序之前,您无法做到这一点。
There are a number of workaround objects you have in the meantime:
在此期间,您有许多变通方法对象:
- Wrap the fields in getters, and lazily load the value. This is a good way (and my personal recommendation) to do it if a field is never ever allowed to be
null
, but they do need to be mutable. - 将字段包装在getter中,然后懒洋洋地加载值。如果永远不允许字段为空,这是一种很好的方式(以及我的个人建议),但它们确实需要是可变的。
- Mark the default fields as
final
. This a good way to do it if they are immutable. - 将默认字段标记为final。如果它们是不可变的,这是一个很好的方法。
- Create a custom
ExclusionStrategy
, and mark the particular fields that should be ignored usingFieldAttributes
- This is the most versatile of the options but also the most code.
- 这是最通用的选项,但也是最多的代码。
- 创建自定义ExclusionStrategy,并使用FieldAttributes标记应忽略的特定字段。这是最通用的选项,但也是最多的代码。
- Deserialize your POJO using just the fields that don't exist, and then compose that data structure with a new one that has the default values.
- 仅使用不存在的字段反序列化您的POJO,然后使用具有默认值的新数据组成该数据结构。
I agree that all of these have drawbacks, but as I said above, this is an open issue with Gson.
我同意所有这些都有缺点,但正如我上面所说,这是Gson的一个悬而未决的问题。
#2
1
Using Gson v2.7, I can see that it calls the default constructor of the deserialized object and any value initialized inside that is retained. However, I was using "new Gson()" instead of "GsonBuilder", if that makes any difference.
使用Gson v2.7,我可以看到它调用了反序列化对象的默认构造函数,并保留了内部初始化的任何值。但是,我使用的是“new Gson()”而不是“GsonBuilder”,如果这有任何区别的话。