如何使用 jersey-media-moxy map/convert 嵌套参数?

How to map/convert nested params with jersey-media-moxy?

我正在使用 jersey 和 MOXy 编写一个 RESTful Web 应用程序,以支持基于 JSON 的 JAXB。

我的目标是使用 POJO 作为使用 JSON 的方法参数。

@POST
@Consumes(MediaType.APPLICATION_JSON)
public void postRequest(MyPOJO myPOJO) {
    System.out.println(myPOJO.name);
    System.out.println(myPOJO.currency);
}

这个 POJO 有一个字符串成员和一个 java.util.Currency 类型的成员。

@XmlRootElement
public class MyPOJO {
    public String name;
    public Currency currency;
    public MyPOJO() {};
}

我还有一个自定义的 Currency ParamConverter(和 Provider),见下文。有了这个,我能够正确处理 Currency 类型的 QueryParam。

但是如果我通过 POST 使用以下内容查询我的资源 JSON 内容货币未映射并且在正确映射名称时将为空。

{ "name": "peter", "currency": "EUR" }

控制台输出结果为:

peter
null

我还需要做什么来告诉 MOXy 正确映射这个嵌套对象成员?

这是我的货币 ParamConverter:

@Provider
public class CurrencyParamConverterProvider implements ParamConverterProvider {
    @Override
    public <T> ParamConverter<T> getConverter(final Class<T> rawType, Type genericType, Annotation[] annotations) {
        return rawType != Currency.class ? null : new ParamConverter<T>() {
            @Override
            public T fromString(String value) {
                if (value == null) {
                    throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
                }

                try {
                    return rawType.cast(Currency.getInstance(value));
                } catch (IllegalArgumentException e) {
                    throw new ExtractorException("Currency must be a valid ISO 4217 code of the currency.", e);
                }
            }

            @Override
            public String toString(T value) {
                if (value == null) {
                    throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value"));
                }
                return value.toString();
            }
        };
    }
}

Currency是一个对象,所以在JSON的世界里,应该是

{ "name": "peter", "currency": { "fieldName" :"EUR"} }

您没有收到任何失败通知的原因是默认情况下 MOXy 只是意味着忽略这些类型的 missing/unknown 属性 问题。

解决这个问题的一种方法是使用 XmlAdapter。例如

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class CurrencyAdapter extends XmlAdapter<String, Currency>{

    @Override
    public Currency unmarshal(String v) throws Exception {
        Currency c = new Currency();
        c.type = v;
        return c;
    }

    @Override
    public String marshal(Currency v) throws Exception {
        return v.type;
    }  
}

其中 Currency.type 只是保存 "EUR" 值的字段。然后你只需要用适配器

注释property/field
@XmlRootElement
public class MyPojo {
    public String name;
    @XmlJavaTypeAdapter(CurrencyAdapter.class)
    public Currency currency;
}