将嵌套/递归 JSON 反序列化为具有继承的 Java 对象
Deserializing nested / recursive JSON into Java objects with inheritance
我有一个 json,它是 complex/nested。我的 json 文件包含两个等效的 java 对象。一个是 Complex_Expression
,另一个是 Simple_Expression
。
Complex_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
and/orSimple_Expression
。 json 文件始终从 Complex_Expression
开始。我必须反序列化这个 JSON 文件。我的最终目标是使用 Complex_Expression
和 Simple_Expression
对象以及这些 class 中的一些逻辑来创建一个表达式。我不介意使用 jackson
或 gson
或者其他依赖项。
到目前为止,我已经创建了一个名为 Expression
的基础 class。 Complex_Expression
和 Simple_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
,这就是为什么有默认构造函数来设置它的原因。如果不需要,可以删除默认构造函数。
我有一个 json,它是 complex/nested。我的 json 文件包含两个等效的 java 对象。一个是 Complex_Expression
,另一个是 Simple_Expression
。
Complex_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
and/orSimple_Expression
。 json 文件始终从 Complex_Expression
开始。我必须反序列化这个 JSON 文件。我的最终目标是使用 Complex_Expression
和 Simple_Expression
对象以及这些 class 中的一些逻辑来创建一个表达式。我不介意使用 jackson
或 gson
或者其他依赖项。
到目前为止,我已经创建了一个名为 Expression
的基础 class。 Complex_Expression
和 Simple_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
我冒昧地修改了你的 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
,这就是为什么有默认构造函数来设置它的原因。如果不需要,可以删除默认构造函数。