如何使用jersey-media-moxy映射/转换嵌套参数?

时间:2015-03-29 17:46:21

标签: java json jersey jax-rs moxy

我使用jersey和MOXy为基于JAXB的JSON支持编写RESTful Web应用程序。

我的目标是使用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() {};
}

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

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

{ "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();
            }
        };
    }
}

1 个答案:

答案 0 :(得分:1)

Currency是一个对象,因此在JSON世界中,它应该是

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

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

解决此问题的一种方法是使用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"值的字段。然后你只需要用适配器

注释属性/字段
@XmlRootElement
public class MyPojo {
    public String name;
    @XmlJavaTypeAdapter(CurrencyAdapter.class)
    public Currency currency;
}