将请求正文中的字段自定义解组(在 Jersey 中)到 HashMap 中?

Custom unmarshaling (in Jersey) a field in the request body into a HashMap?

我有一个 Jersey (1.18.1) 服务器,目前期望在 POST 请求中说 Person

<person>
    <name>sdfsdfd</name>
    <age>24</age>
    ...
</person>

上面的请求正文在我的服务器方法中被反序列化为一个人 class(比如 /add

我需要向请求添加一个 options 成员,这样它是可选的,但在传递时应序列化为 Person class 中的 Map<String, String> 成员:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
@XmlRootElement(name = "person")
class Person {
    @XmlElement(required = true)
    private String name;

    @XmlElement(required = true)
    private int age;

    @XmlElement(required = false)
    private Map<String, String> options;

    // ctor, getters, setters etc.
}

我知道我必须编写一个自定义解串器,例如 @XmlJavaTypeAdapter(PersonOptionsAdapter.class). 我在网上找到的关于适配器的内容是在整个请求正文需要自定义解组时使用一个。但是,对于特定成员,这似乎对我不起作用。我尝试用 PersonOptionsAdapter 注释 options 成员,还有一些类似的东西。

请分享您的想法and/or关于如何在请求对象的特定成员上应用自定义适配器的解决方案?

我找到了方法...

这是 JAXB 适配器,需要

<!-- language: java -->
@XmlRootElement
public class JaxbXml2MapAdapter extends XmlAdapter<Object, HashMap<String, String>> {

    public JaxbXml2MapAdapter() {
        super();
    }

    @Override
    public Object marshal(HashMap<String, String> map) throws Exception {
        // I wasn't using it for sending this out in the response. So
        // did not bother to implement marshaling.
        return null;
    }

    @Override
    public HashMap<String, String> unmarshal(Object rawRoot) throws Exception {
        final HashMap<String, String> map = new HashMap<String, String>();

        if (rawRoot == null || !(rawRoot instanceof Element)) {
            return map;
        }

        final Element  root     = (Element) rawRoot;
        final NodeList children = root.getChildNodes();

        if (children.getLength() == 0) {
            return map;
        }

        // TODO: Analyze if there is a better way of reading the nodes.
        // Currently we get null/empty node names, white space values etc.

        for (int index = 0; index < children.getLength(); ++index) {
            final Node   child = children.item(index);
            final String name  = child.getLocalName();

            if (name == null || name.length == 0) {
               continue;
            }

            final String value = child.getTextContent();
            map.put(name, value);
        }

        return map;
    }
}

适配器的使用方法如下:

<!-- language: java -->
@XmlRootElement(name = "myRequest")
public class MyRequest {

    @XmlElement(required = true)
    private String token;

    private List<int> flags = new ArrayList<int>();

    @XmlJavaTypeAdapter(value = JaxbXml2MapAdapter.class)
    private HashMap<String, String> options = new HashMap<String, String>();

    public MyRequest() {
    }

    // .... blah blah blah
}

这是一个示例请求正文( 是一个可选参数):

<!-- language: xml -->
<myRequest>
   <token>QWe35234</token>
   <flags>1</flags>
   <flags>4</flags>
   <options>
       <name>Johnny</name>
       <points>25.3</options>
       <someRandomStuff>sdfsgsagasfgasgsaf</someRandomStuff>
   </options>
</myRequest>

希望对您有所帮助