如何使用 Jackson 通过元素属性将相同的 xml 元素反序列化为不同的 类? (多态反序列化)
How deserialize same xml element to different classes by element attribute with Jackson? (polymorphic deserialization)
我有一个 xml 结构的文件:
<actions shop_id="100500">
<action type="refunds">
<!-- properties collection for refunds -->
</action>
<action type="sales">
<!-- another properties collection for sales -->
</action>
<action type="distributions">
<!-- one more properties collection for distributions -->
</action>
</actions>
如何根据操作类型将操作反序列化为不同的 类?
例如:将<action type="refunds">
映射到Refunds.class
,将<action type="sales">
映射到Sales.class
你要的叫多态反序列化
您需要延长 Refunds
、Sales
和 Distributions
classes 来自一个共同的基础 class(让我们称它为 Action
)。
将具体属性放入这些subclasses
并根据需要用 @JacksonXmlProperty(...)
注释它们。
public class Refunds extends Action {
@JacksonXmlProperty(localName = "a", isAttribute = false)
private int a;
// getters and setters (omitted here for brevity)
}
public class Sales extends Action {
@JacksonXmlProperty(localName = "b", isAttribute = false)
private int b;
// getters and setters (omitted here for brevity)
}
public class Distributions extends Action {
@JacksonXmlProperty(localName = "c", isAttribute = false)
private int c;
// getters and setters (omitted here for brevity)
}
棘手的部分是实现基础 class。
我推荐阅读文章 "Inheritance in Jackson",
特别是它的部分“2.2。Per-Class注释”。
您需要向 Jackson 提供有关映射的足够信息
在你的 subclasses 和 type
属性 之间。
(并且不要被历史注释名称激怒
尽管您正在处理 XML,但以 Json...
开头。)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(name = "refunds", value = Refunds.class),
@JsonSubTypes.Type(name = "sales", value = Sales.class),
@JsonSubTypes.Type(name = "distributions", value = Distributions.class)
})
public abstract class Action {
@JacksonXmlProperty(isAttribute = true)
private String type;
// no getter/setter needed for type
}
最后你需要一个根 class 来代表
全部 <actions>...</actions>
内容。
它的 List<Action>
属性 将得到一个混合物
Refunds
、Sales
和 Distributions
个对象。
@JacksonXmlRootElement(localName = "actions")
public class Actions {
@JacksonXmlProperty(localName = "shop_id", isAttribute = true)
private String shopId;
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "action", isAttribute = false)
private List<Action> actions;
// getters and setters (omitted here for brevity)
}
使用上面的 classes 和 Jackson 的 XmlMapper
你
能够像这样读写 XML 内容。
<actions shop_id="100500">
<action type="refunds">
<a>1</a>
</action>
<action type="sales">
<b>2</b>
</action>
<action type="distributions">
<c>3</c>
</action>
</actions>
我有一个 xml 结构的文件:
<actions shop_id="100500">
<action type="refunds">
<!-- properties collection for refunds -->
</action>
<action type="sales">
<!-- another properties collection for sales -->
</action>
<action type="distributions">
<!-- one more properties collection for distributions -->
</action>
</actions>
如何根据操作类型将操作反序列化为不同的 类?
例如:将<action type="refunds">
映射到Refunds.class
,将<action type="sales">
映射到Sales.class
你要的叫多态反序列化
您需要延长 Refunds
、Sales
和 Distributions
classes 来自一个共同的基础 class(让我们称它为 Action
)。
将具体属性放入这些subclasses
并根据需要用 @JacksonXmlProperty(...)
注释它们。
public class Refunds extends Action {
@JacksonXmlProperty(localName = "a", isAttribute = false)
private int a;
// getters and setters (omitted here for brevity)
}
public class Sales extends Action {
@JacksonXmlProperty(localName = "b", isAttribute = false)
private int b;
// getters and setters (omitted here for brevity)
}
public class Distributions extends Action {
@JacksonXmlProperty(localName = "c", isAttribute = false)
private int c;
// getters and setters (omitted here for brevity)
}
棘手的部分是实现基础 class。
我推荐阅读文章 "Inheritance in Jackson",
特别是它的部分“2.2。Per-Class注释”。
您需要向 Jackson 提供有关映射的足够信息
在你的 subclasses 和 type
属性 之间。
(并且不要被历史注释名称激怒
尽管您正在处理 XML,但以 Json...
开头。)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(name = "refunds", value = Refunds.class),
@JsonSubTypes.Type(name = "sales", value = Sales.class),
@JsonSubTypes.Type(name = "distributions", value = Distributions.class)
})
public abstract class Action {
@JacksonXmlProperty(isAttribute = true)
private String type;
// no getter/setter needed for type
}
最后你需要一个根 class 来代表
全部 <actions>...</actions>
内容。
它的 List<Action>
属性 将得到一个混合物
Refunds
、Sales
和 Distributions
个对象。
@JacksonXmlRootElement(localName = "actions")
public class Actions {
@JacksonXmlProperty(localName = "shop_id", isAttribute = true)
private String shopId;
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "action", isAttribute = false)
private List<Action> actions;
// getters and setters (omitted here for brevity)
}
使用上面的 classes 和 Jackson 的 XmlMapper
你
能够像这样读写 XML 内容。
<actions shop_id="100500">
<action type="refunds">
<a>1</a>
</action>
<action type="sales">
<b>2</b>
</action>
<action type="distributions">
<c>3</c>
</action>
</actions>