【问题标题】:How to deserialize json string to different specific java Objec?如何将 json 字符串反序列化为不同的特定 java 对象?
【发布时间】:2022-01-11 03:21:52
【问题描述】:

我设法使用 gson 将一个极其复杂的类(其中嵌套了 50 个自定义 java 对象)序列化为 json 字符串。 这是我的一部分对象:

public class MyComplexObject{
     private int a;
     private String b;
     private MyclassA c;
     ...
     private map<String, Object> x;
}

请注意,对于字段private map&lt;String, Object&gt; x,VALUE Object 可以是IntegerDoubleStringmyClassC 等...... 序列化的时候效果很好,但是反序列化的时候gson无法按照我的预期转换json字符串。

MyClassC:

public class MyclassC{
    public String d;
    public List<Integer> e;
}

这是一个例子:

MyComplexObject myComplexObject = new MyComplexObject();
myComplexObject.seta(1);
myComplexObject.setb("abc");

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
MyClassC myClassC = new MyClassC("key1", list);
myComplexObject.setx(myClassC);

// Serializing and Deserializing
String myComplexObjectStr = gson.toJson(myComplexObject);
MyComplexObject myComplexObject2 = gson.fromJson(myComplexObjectStr, MyComplexObject.class);

// after deserializing, x has been converted to LinkedTreeMap
myComplexObject.x.getClass();   // class MyClassC
myComplexObject2.x.getClass();   // class com.google.gson.internal.LinkedTreeMap

// Go further about the field x

Object object = myComplexObject2.x.get("key1");

LinkedTreeMap linkedTreeMap = (LinkedTreeMap) object;
ArrayList arrayList = (ArrayList) linkedTreeMap.get("e");

arrayList.get(0).getClass(); // class java.lang.Double

所以在序列化和反序列化之后:

  1. MyClassC 已转换为 LinkedTreeMap
  2. List 已转换为 List

所以我的问题是:我应该怎么做才能确保MyComplexObject在序列化和反序列化后完全相同?

【问题讨论】:

  • 您能否提供一个可验证的最小示例?通常,您只需在 Java 类中指定类型即可。对于您的示例,这将类似于public class MyClass { public Integer keyA; }。如果您不限于 GSON,您还可以考虑 jackson(在 Spring 中很流行,但在 EE 中也很流行)甚至 yasson(JSON-B EE 标准的参考实现)。
  • 我已经更新了我的帖子以清楚地描述它,感谢您的建议。

标签: java serialization gson deserialization


【解决方案1】:

当使用 Gson 将 JSON 数字反序列化为 Object 时,它默认将 JSON 值反序列化为 Java Double(如您所见)。最近在 Gson 2.8.9 中添加了一个新功能,允许指定 ToNumberStrategy。这使您可以更轻松地影响 Gson 如何反序列化 JSON 数字。 ToNumberPolicy 枚举提供了一些默认实现。最接近您要求的是ToNumberPolicy.LONG_OR_DOUBLE。如果你真的需要 Integer 作为值类型,你可以尝试编写类似于Gson's one 的自己的实现。

【讨论】:

  • 我试试,谢谢!
  • 我设法编写了我的 ToNumberPolicy.INTEGER_OR_DOUBLE 实现,它可以正常工作,再次感谢您!
  • @cspeng1,没问题。能否请mark my answer as accepted 表明此问题已得到解答?
猜你喜欢
  • 2023-03-28
  • 2020-02-03
  • 1970-01-01
  • 2018-11-01
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多