Jackson的多态反序列化,使用父属性值

huangapple go评论83阅读模式
英文:

Polymorphic deserialization of jackson using parent property value

问题

I have translated the provided content. Here's the translated code:

我有一个如下所示的 JSON

{
"transformationRules": [
{
"targetFieldName": "pageUrlNumber",
"inputPath": "$.metadata.pageUrl",
"rules": [
{
"name": "regex",
"regexPattern": "\d+",
"regexTransformType": "extract",
"order":2
}
]
},
{
"targetFieldName": "categories",
"inputPath": "$.attributes[0].productInfo.breadCrumbs",
"rules": [
{
"name": "transform"
}
]
}
]
}


`rules` 数组具有不同类的 JSON。

我希望根据名称的值即 regex、transform,将上述 JSON 转换为它们的 POJO。我尝试了以下代码。

Rule.java

```java
@NoArgsConstructor
@Data
@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
        property = "name")
@JsonSubTypes({
        @JsonSubTypes.Type(value = RegexRule.class, name = "regex"),
        @JsonSubTypes.Type(value = Transform.class, name = "transform"),
})
public abstract class Rule {

    @JsonProperty("name")
    private String name;

    @JsonProperty("order")
    private int order = 1;

    protected Rule(String name, int order) {
        this.name = name;
        this.order = order;
    }

}

RegexRule.java

@NoArgsConstructor
@Data
public class RegexRule extends Rule{

    @JsonProperty("regexPattern")
    private String regexPattern;

    @JsonProperty("regexTransformType")
    private String regexTransformType;

    @JsonProperty("replacementValue")
    private String replacementValue = "";

    @JsonProperty("regexGroupNumber")
    private int regexGroupNumber = 0;

    public RegexRule(String name, int order, String regexPattern, String regexTransformType, String replacementValue, int regexGroupNumber) {
        super(name, order);
        this.regexGroupNumber = regexGroupNumber;
        this.regexPattern = regexPattern;
        this.regexTransformType = regexTransformType;
        this.replacementValue = replacementValue;
    }
}

Transform.java

@NoArgsConstructor
@Data
public class Transform extends Rule{

    public Transform(String name, int order) {
        super(name, order);
    }
}

Main.java

for (TransformationRule transformationRule : getTransformationRules()) {
    for (Rule rule : transformationRule.getRules()) {
        System.out.println(rule.getName());
    }
}

输出:

null
null

在我的 Main 函数中,当我将 JSON 反序列化为 POJO 时,我得到的名称为 null。而我应该得到 regextransform 作为输出。我在这里犯了什么错误?我需要名称用于一个工厂方法。


<details>
<summary>英文:</summary>

I have a json as follows:

{
"transformationRules": [
{
"targetFieldName": "pageUrlNumber",
"inputPath": "$.metadata.pageUrl",
"rules": [
{
"name": "regex",
"regexPattern": "\d+",
"regexTransformType": "extract",
"order":2
}
]
},
{
"targetFieldName": "categories",
"inputPath": "$.attributes[0].productInfo.breadCrumbs",
"rules": [
{
"name": "transform"
}
]
}
]
}

The `rules` array has json of different classes. 

I want convert the above json to their pojos depending on the value of the name i.e regex, transform. I have tried the following code.

Rule.java

@NoArgsConstructor
@Data
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "name")
@JsonSubTypes({
@JsonSubTypes.Type(value = RegexRule.class, name = "regex"),
@JsonSubTypes.Type(value = Transform.class, name = "transform"),
})
public abstract class Rule {

@JsonProperty(&quot;name&quot;)
private String name;

@JsonProperty(&quot;order&quot;)
private int order = 1;

protected Rule(String name, int order) {
    this.name = name;
    this.order = order;
}

}


RegexRule.java

@NoArgsConstructor
@Data
public class RegexRule extends Rule{

@JsonProperty(&quot;regexPattern&quot;)
private String regexPattern;

@JsonProperty(&quot;regexTransformType&quot;)
private String regexTransformType;

@JsonProperty(&quot;replacementValue&quot;)
private String replacementValue = &quot;&quot;;

@JsonProperty(&quot;regexGroupNumber&quot;)
private int regexGroupNumber = 0;

public RegexRule(String name, int order, String regexPattern, String regexTransformType, String replacementValue, int regexGroupNumber) {
    super(name, order);
    this.regexGroupNumber = regexGroupNumber;
    this.regexPattern = regexPattern;
    this.regexTransformType = regexTransformType;
    this.replacementValue = replacementValue;
}

}


Transform.java

@NoArgsConstructor
@Data
public class Transform extends Rule{

public Transform(String name, int order) {
    super(name, order);
}

}

Main.java

for(TransformationRule transformationRule: getTransformationRules()){
for(Rule rule:transformationRule.getRules()){
System.out.println(rule.getName());
}
}


Output:

null
null



In my Main function, when I deserialize the json to the pojos, I&#39;m getting name as null. Instead I should get `regex` and `transform` as output

What mistake have I done here? I need the name for a factory method

</details>


# 答案1
**得分**: 2

`As.EXTERNAL_PROPERTY` 在这里听起来不太对,如果这个方式真的有效,我会感到惊讶,因为这会意味着:

```json
{
  "name": "regex", // 这是*外部*属性,位于上一级
  { // 这是 Rule
    "order": 2,
    ...
  }
}

尝试以下选项:

  • As.PROPERTY
    • 你可以从 POJO 中删除 Rule#name,因为它被视为元数据,仅供 Jackson 正确反序列化时使用。记住 rule.getName() == "regex"rule instanceof RegexRule 是一样的。
  • As.EXISTING_PROPERTY
    • 将会按预期填充字段,但在大规模使用时可能会稍微影响性能(只有在应用程序持续执行此操作时才会有影响)。
    • 查看 原始功能请求 以获取另一个示例。
英文:

As.EXTERNAL_PROPERTY sounds wrong here and I'm surprised if that worked at all, that would imply:

{
  &quot;name&quot;: &quot;regex&quot;, // This is the *external* property, one level up
  { // this is the Rule
    &quot;order&quot;: 2,
    ...
  }
}

Try

  • As.PROPERTY

    • You can delete Rule#name from the POJO as it is treated as meta-data existing only for Jackson to deserialise correctly. Remember rule.getName()==&quot;regex&quot; is the same as rule instanceof RegexRule
  • As.EXISTING_PROPERTY

    • Will populate the field as you expected but might have slightly worse performance at scale (only matters if this is something the app is doing continuously)
    • See the original feature request for another example

huangapple
  • 本文由 发表于 2020年7月31日 15:04:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/63187221.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定