通过继承将嵌套/递归JSON反序列化为Java对象

时间:2018-09-25 09:07:32

标签: java json jackson gson json-deserialization

我有一个复杂/嵌套的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,没问题)组成。

1 个答案:

答案 0 :(得分: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的类型,这就是为什么有默认构造函数对此进行设置的原因。如果不需要它,则可以删除默认构造函数。