Jackson:不同的 XML 和 JSON 格式
Jackson: different XML and JSON format
在我基于 Apache wink 的 REST 项目中,我们使用 Jackson jax-rs 提供程序来处理 JSON 和 XML 内容类型。我们的响应对象包含一个 HashMap<String, PropertyObject>
。映射键包含空格,因此不能序列化为 XML 元素名称。 JSON 序列化工作正常。
JSON格式:
{
"properties": {
"a b c": {
"name": "a b c",
"type": "Double",
"value": "2.0"
},
"x y z": {
"name": "x y z",
"type": "Double",
"value": "0.0"
}
}
}
需要XML格式
<rootElement>
<Property name="a b c" type="double" value="2.0">
<Property name="x y z" type="double" value="0.0">
</rootElement>
我们如何使用 Jackson jax-rs XML 和 JSON 提供程序实现此目的。是否可以定义自定义 jackson 序列化程序并扩展 jax-rs 提供程序。请提出最佳方法。
您可以更改 XML 的一种方法是使用 JAXB XmlAdapter
。像
public class PropertyAdapter extends XmlAdapter<PropertyAdapter.AdaptedProperties,
HashMap<String, PropertyObject>> {
public static class AdaptedProperties {
public ArrayList<PropertyObject> property = new ArrayList<>();
}
@Override
public HashMap<String, PropertyObject> unmarshal(
PropertyAdapter.AdaptedProperties list) throws Exception {
HashMap<String, PropertyObject> map = new HashMap<>();
for (PropertyObject prop: list.property) {
map.put(prop.getName(), prop);
}
return map;
}
@Override
public PropertyAdapter.AdaptedProperties marshal(
HashMap<String, PropertyObject> map) throws Exception {
ArrayList<PropertyObject> list = new ArrayList<>(map.values());
AdaptedProperties props = new AdaptedProperties();
props.property = list;
return props;
}
}
然后只需注释 field/property
@XmlRootElement
public class DTO {
private HashMap<String, PropertyObject> properties;
@XmlJavaTypeAdapter(PropertyAdapter.class)
public HashMap<String, PropertyObject> getProperties() {
return properties;
}
// setter
}
这将是结果。这不是你想要的,但我不知道如何在没有 <properties>
包装器的情况下获得它。
<root>
<properties>
<property name="a b c" type="Double" value="2.0"/>
<property name="x y z" type="Double" value="0.0"/>
</properties>
</root>
您还需要确定的一件事是,当您使用 Jackson 时,您没有使用配置了 JAXB 注释支持的提供程序。如果您使用此提供程序,它将使用 XmlAdapter
并且您将获得一个 JSON 数组,而不是像您当前拥有的 object/map 。假设您使用的是 this provider,它有一个 JacksonJaxbJsonProvider
和一个普通的 JacksonJsonProvider
。您要确保只注册后者。
编辑
哦,我忘了补充一点,我用来测试的 PropertyObject
class 看起来像这样
@XmlRootElement
public class PropertyObject {
private String name;
@XmlAttribute(name = "name")
public String getName() {
return name;
}
// There are `type` and `value` fields also, with corresponding
// getters and setters, both using the `@XmlAttribute`
}
更新
假设您确实想要 JAXB 注释支持 Jackson JSON 序列化。您可以做的是配置您自己的 ObjectMapper
,并且只使用支持 JAXB 的那个 class。你可以看到那是怎样的
在我基于 Apache wink 的 REST 项目中,我们使用 Jackson jax-rs 提供程序来处理 JSON 和 XML 内容类型。我们的响应对象包含一个 HashMap<String, PropertyObject>
。映射键包含空格,因此不能序列化为 XML 元素名称。 JSON 序列化工作正常。
JSON格式:
{
"properties": {
"a b c": {
"name": "a b c",
"type": "Double",
"value": "2.0"
},
"x y z": {
"name": "x y z",
"type": "Double",
"value": "0.0"
}
}
}
需要XML格式
<rootElement>
<Property name="a b c" type="double" value="2.0">
<Property name="x y z" type="double" value="0.0">
</rootElement>
我们如何使用 Jackson jax-rs XML 和 JSON 提供程序实现此目的。是否可以定义自定义 jackson 序列化程序并扩展 jax-rs 提供程序。请提出最佳方法。
您可以更改 XML 的一种方法是使用 JAXB XmlAdapter
。像
public class PropertyAdapter extends XmlAdapter<PropertyAdapter.AdaptedProperties,
HashMap<String, PropertyObject>> {
public static class AdaptedProperties {
public ArrayList<PropertyObject> property = new ArrayList<>();
}
@Override
public HashMap<String, PropertyObject> unmarshal(
PropertyAdapter.AdaptedProperties list) throws Exception {
HashMap<String, PropertyObject> map = new HashMap<>();
for (PropertyObject prop: list.property) {
map.put(prop.getName(), prop);
}
return map;
}
@Override
public PropertyAdapter.AdaptedProperties marshal(
HashMap<String, PropertyObject> map) throws Exception {
ArrayList<PropertyObject> list = new ArrayList<>(map.values());
AdaptedProperties props = new AdaptedProperties();
props.property = list;
return props;
}
}
然后只需注释 field/property
@XmlRootElement
public class DTO {
private HashMap<String, PropertyObject> properties;
@XmlJavaTypeAdapter(PropertyAdapter.class)
public HashMap<String, PropertyObject> getProperties() {
return properties;
}
// setter
}
这将是结果。这不是你想要的,但我不知道如何在没有 <properties>
包装器的情况下获得它。
<root>
<properties>
<property name="a b c" type="Double" value="2.0"/>
<property name="x y z" type="Double" value="0.0"/>
</properties>
</root>
您还需要确定的一件事是,当您使用 Jackson 时,您没有使用配置了 JAXB 注释支持的提供程序。如果您使用此提供程序,它将使用 XmlAdapter
并且您将获得一个 JSON 数组,而不是像您当前拥有的 object/map 。假设您使用的是 this provider,它有一个 JacksonJaxbJsonProvider
和一个普通的 JacksonJsonProvider
。您要确保只注册后者。
编辑
哦,我忘了补充一点,我用来测试的 PropertyObject
class 看起来像这样
@XmlRootElement
public class PropertyObject {
private String name;
@XmlAttribute(name = "name")
public String getName() {
return name;
}
// There are `type` and `value` fields also, with corresponding
// getters and setters, both using the `@XmlAttribute`
}
更新
假设您确实想要 JAXB 注释支持 Jackson JSON 序列化。您可以做的是配置您自己的 ObjectMapper
,并且只使用支持 JAXB 的那个 class。你可以看到那是怎样的