【问题标题】:Deserializing nested / recursive JSON into Java objects with inheritance通过继承将嵌套/递归 JSON 反序列化为 Java 对象
【发布时间】:2018-09-25 09:07:31
【问题描述】:

我有一个复杂/嵌套的 json。我的 json 文件由两个等效的 java 对象组成。一个是Complex_Expression,另一个是Simple_ExpressionComplex_Expression 格式如下:

{
    "SomeOpearator":0,
    "ASpecificKey":1, //the value 1 is fixed for complex expression.
    "Expressions":[ ] //array of one or more expressions
}

Simple Expression 格式如下:

{
    "Operand":"Some String Value",
    "ASpecificKey":0, //the value 0 is fixed for simple expressions.
    "SomeComparisionOpearator":1, // enums which associates int to different comparison operators.
    "Value":["String1"] //this is an array of strings.
}

Expressions 又可以有Complex_Expression 和/或Simple_Expression。 json 文件总是从Complex_Expression 开始。我必须反序列化这个 JSON 文件。我的最终目标是使用Complex_ExpressionSimple_Expression 对象以及这些类中的一些逻辑来制作表达式。我不介意使用 jacksongson 或其他依赖项。

到目前为止,我已经创建了一个名为Expression 的基类。 Complex_ExpressionSimple_Expression 都继承了这个类。然后我开始写Custom Json Deserializer。但是在自定义反序列化器中,我被卡住了,我不知道该怎么做。请帮助我。我的Simple_Expression 类看起来像这样,与Complex_Expression 类有些相似。

public class Simple_Expression extends Expression
{
    @JsonProperty("Operand") //use jackson deserializer for this class.
    public String Operand;

    @JsonProperty("SomeComparisionOpearator")
    public SomeComparisionOpearator someCompareOperator;

    @JsonProperty("Value")
    public Object value;

    public Simple_Expression()
    {
        super(ASpecificKey.Simple); //Simple corresponds to 0
    }
}

更新

关于我的输入和输出的更多描述。输入给定一个 JSON 字符串,如下所示:

{
  "SomeOpearator": 0,
  "ASpecificKey": 1,
  "Expressions": [
    {
      "SomeOpearator": 1,
      "ASpecificKey": 1,
      "Expressions": [
        {
          "Operand": "People",
          "ASpecificKey": 0,
          "SomeComparisionOpearator": 14,
          "Value": [
            "Rich"
          ]
        }
      ]
    },
    {
      "SomeOpearator": 1,
      "ASpecificKey": 1,
      "Expressions": [
        {
          "Operand": "Grade",
          "ASpecificKey": 0,
          "SomeComparisionOpearator": 2,
          "Value": [
            "Grade A"
          ]
        }
      ]
    }
  ]
}

假设杰克逊反序列化器,我应该能够做这样的事情:

ObjectMapper mapper = new ObjectMapper();
Expression myExpressionObject = mapper.convertValue(jsonString, Expression.class);

它应该将反序列化的对象放入 myExpressionObject 中,该对象将包含一个表达式列表(Arraylist 或 Array,没问题)。

【问题讨论】:

  • 你应该分享你的java代码和序列化/反序列化的预期输入/输出数据示例

标签: java json jackson gson json-deserialization


【解决方案1】:

使用 Gson extras RuntimeTypeAdapterFactory 这将很容易,因为您拥有可用作类型鉴别器的字段 ASpecificKey。用法见this。如果您已经包含 Gson,则可以将源代码复制到您的项目中。

我冒昧地修正了你的 Java 命名约定,所以类实际上看起来像(你的 JSON 也应该被修正为正确的约定):

@Getter @Setter
public class Expression {
    private int aSpecificKey;
}

@Getter @Setter
public class SimpleExpression extends Expression {
    public SimpleExpression() {
        setASpecificKey(0);
    }
    private String operand;
    private int someComparisonOperator;
    private String[] values; 
}

@Getter @Setter
public class ComplexExpression extends Expression {
    public ComplexExpression() {
        setASpecificKey(1);
    }   
    private String someOperator;
    private Expression[] expressions;
}

针对这种 DTO,您只需实例化一个特定的 RuntimeTypeAdapterFactory

final RuntimeTypeAdapterFactory<Expression> expressionTypeFactory = 
    RuntimeTypeAdapterFactory               
        .of(Expression.class, "aSpecificKey")
        .registerSubtype(SimpleExpression.class, "0")
        .registerSubtype(ComplexExpression.class, "1")

然后反序列化就像:

Expression e = getGson(expressionTypeFactory)
        .fromJson(getPackageResourceReader(YOUR_NOTATION_FIXED_JSON),
                                               Expression.class);

请注意,默认情况下 Gson 不会反序列化类型鉴别器 aSpecificKey,这就是为什么存在设置它的默认构造函数的原因。如果您不需要它,您可以删除默认构造函数。

【讨论】:

  • 我的 someComparisonOperatorsomOperator 键实际上是枚举,例如`Equals,NotEquals...`。当我使用它反序列化时。这些字段自动分配为空。我是否也需要更改枚举类?
  • @SunilKumar 将您的枚举类添加到问题中,并至少添加一个模型类您如何使用它,例如private EnumOperator someComparisonOperator?。你也可以看看this question
  • 没关系。在上面链接的帮助下,我做到了。谢谢!!
猜你喜欢
  • 2017-12-28
  • 2017-12-28
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 2016-12-12
  • 2017-10-29
  • 2018-03-20
相关资源
最近更新 更多