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。你可以看到那是怎样的