英文:
Deserializing json subtype based on parent property
问题
我有一个带有动态attribute
子项的 JSON,如下所示:
{
"label":"Some label",
"attribute": {
"type": "TEXT",
"languages":[
{
"language":"en_EN",
"text":"do you approve?"
}
]
}
}
或者
{
"label":"Some label",
"attribute": {
"type": "NUMBER",
"value": "10.0"
}
}
我能够使用以下代码正确反序列化上述 JSON,其中使用了@JsonSubTypes
:
@Data
public class Field {
private String label;
private Attribute attribute;
}
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Attribute.NumberAttribute.class, name = "NUMBER"),
@JsonSubTypes.Type(value = Attribute.TextAttribute.class, name = "TEXT")
})
public class Attribute {
private AttributeType type;
@Data
public static class TextAttribute extends Attribute {
List<Language> languages;
}
@Data
public static class NumberAttribute extends Attribute {
String value;
}
@Data
public static class Language {
private String text;
private String language;
}
}
然而,我遇到的问题是,我必须使用 attribute 对象内部的 type
字段,我希望将 type 移到父对象中。最终的 JSON 应该像这样:
{
"type": "TEXT",
"label":"Some label",
"attribute": {
"languages":[
{
"language":"en_EN",
"text":"do you approve?"
}
]
}
}
或者
{
"type": "NUMBER",
"label":"Some label",
"attribute": {
"value": "10.0"
}
}
我找不到任何方法来使用父字段(或 JSON 路径方式)来使用位于动态子类型之外的 type
属性。你知道我如何做到这一点吗?
英文:
I have a json coming with a dynamic attribute
child, like below:
{
"label":"Some label",
"attribute": { <--- Dynamic attribute object
"type": "TEXT", <--- Field used to map `attribute` dynamic (inside child object)
"languages":[
{
"language":"en_EN",
"text":"do you approve?"
}
]
}
}
Or
{
"label":"Some label",
"attribute": {
"type": "NUMBER",
"value: "10.0"
}
}
I am able to deserialize above json properly using @JsonSubTypes
with this code:
@Data
public class Field {
private String label;
private Attribute attribute;
}
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Attribute.NumberAttribute.class, name = "NUMBER"),
@JsonSubTypes.Type(value = Attribute.TextAttribute.class, name = "TEXT")
})
public class Attribute {
private AttributeType type;
@Data
public static class TextAttribute extends Attribute {
List<Language> languages;
}
@Data
public static class NumberAttribute extends Attribute {
String value;
}
@Data
public static class Language {
private String text;
private String language;
}
}
However, the problem I have is that I have to use type
field coming inside the attribute object, and I would need to move the type to the parent object. The ending json should be like this:
{
"type": "TEXT", <--- Field used to map `attribute` dynamic (in parent object)
"label":"Some label",
"attribute": { <--- Dynamic attribute object
"languages":[
{
"language":"en_EN",
"text":"do you approve?"
}
]
}
}
Or
{
"type": "NUMBER",
"label":"Some label",
"attribute": {
"value: "10.0"
}
}
I couldn't find any way to use a parent field (or json path way) to use the type
property being outside the dynamic subtype. Do you know how I can do this?
答案1
得分: 5
你可以通过在@JsonTypeInfo
中添加 include = As.EXTERNAL_PROPERTY
来实现这一点。你只需要将该注解移到字段上。
关于 EXTERNAL_PROPERTY,你可以参考 JavaDoc 中的说明:
类似于 PROPERTY 的包含机制,不同之处在于属性在层次结构中包含在更高的一级 [...]
以下是一个示例:
@Data
class Field {
private String label;
private AttributeType attributeType;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.EXTERNAL_PROPERTY, property = "attributeType")
private Attribute attribute;
}
@Data
@JsonSubTypes({
@JsonSubTypes.Type(value = Attribute.NumberAttribute.class, name = "NUMBER"),
@JsonSubTypes.Type(value = Attribute.TextAttribute.class, name = "TEXT")
})
abstract class Attribute {
@Data
public static class TextAttribute extends Attribute {
List<Language> languages;
}
@Data
public static class NumberAttribute extends Attribute {
String value;
}
@Data
public static class Language {
private String text;
private String language;
}
}
enum AttributeType {
NUMBER, TEXT;
}
英文:
You can achieve that by adding include = As.EXTERNAL_PROPERTY
to @JsonTypeInfo
. You just have to move the annotation to the field.
See the JavaDoc for EXTERNAL_PROPERTY:
> Inclusion mechanism similar to <code>PROPERTY</code>, except that property is included one-level higher in hierarchy [...]
Here's an example:
@Data
class Field {
private String label;
private AttributeType attributeType;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.EXTERNAL_PROPERTY, property = "attributeType")
private Attribute attribute;
}
@Data
@JsonSubTypes({
@JsonSubTypes.Type(value = Attribute.NumberAttribute.class, name = "NUMBER"),
@JsonSubTypes.Type(value = Attribute.TextAttribute.class, name = "TEXT")
})
abstract class Attribute {
@Data
public static class TextAttribute extends Attribute {
List<Language> languages;
}
@Data
public static class NumberAttribute extends Attribute {
String value;
}
@Data
public static class Language {
private String text;
private String language;
}
}
enum AttributeType {
NUMBER, TEXT;
}
答案2
得分: 1
@Data
public class Field {
private String label;
private AttributeType type;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(value = Attribute.NumberAttribute.class, name = "NUMBER"),
@JsonSubTypes.Type(value = Attribute.TextAttribute.class, name = "TEXT")
})
private Attribute attribute;
}
@Data
public class Attribute {
@Data
public static class TextAttribute extends Attribute {
List<Language> languages;
}
@Data
public static class NumberAttribute extends Attribute {
String value;
}
@Data
public static class Language {
private String text;
private String language;
}
}
英文:
I'm posting this as an alternative in case accepted answer doesn't work for others:
@Data
public class Field {
private String label;
private AttributeType type;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(value = Attribute.NumberAttribute.class, name = "NUMBER"),
@JsonSubTypes.Type(value = Attribute.TextAttribute.class, name = "TEXT")
})
private Attribute attribute;
}
@Data
public class Attribute {
@Data
public static class TextAttribute extends Attribute {
List<Language> languages;
}
@Data
public static class NumberAttribute extends Attribute {
String value;
}
@Data
public static class Language {
private String text;
private String language;
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论