将嵌套/递归 JSON 反序列化为具有继承的 Java 对象

Deserializing nested / recursive JSON into Java objects with inheritance

我有一个 json,它是 complex/nested。我的 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_Expressionand/orSimple_Expression。 json 文件始终从 Complex_Expression 开始。我必须反序列化这个 JSON 文件。我的最终目标是使用 Complex_ExpressionSimple_Expression 对象以及这些 class 中的一些逻辑来创建一个表达式。我不介意使用 jacksongson 或者其他依赖项。

到目前为止,我已经创建了一个名为 Expression 的基础 class。 Complex_ExpressionSimple_Expression 都继承了这个 class。然后我开始写Custom Json Deserializer。但是在自定义反序列化器中,我被卡住了,我不知道该如何进行。请帮我解决这个问题。我的 Simple_Expression class 看起来像这样,有点相似的是 Complex_Expression class.

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"
          ]
        }
      ]
    }
  ]
}

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

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

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

使用 Gson extras RuntimeTypeAdapterFactory because you have the field ASpecificKey that can be used as type discriminator. See 这会很容易。如果您已经包含 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,这就是为什么有默认构造函数来设置它的原因。如果不需要,可以删除默认构造函数。