英文:
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。而我应该得到 regex
和 transform
作为输出。我在这里犯了什么错误?我需要名称用于一个工厂方法。
<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("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());
}
}
Output:
null
null
In my Main function, when I deserialize the json to the pojos, I'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
是一样的。
- 你可以从 POJO 中删除
As.EXISTING_PROPERTY
- 将会按预期填充字段,但在大规模使用时可能会稍微影响性能(只有在应用程序持续执行此操作时才会有影响)。
- 查看 原始功能请求 以获取另一个示例。
英文:
As.EXTERNAL_PROPERTY
sounds wrong here and I'm surprised if that worked at all, that would imply:
{
"name": "regex", // This is the *external* property, one level up
{ // this is the Rule
"order": 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. Rememberrule.getName()=="regex"
is the same asrule instanceof RegexRule
- You can delete
-
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论