【问题标题】:How to map/convert nested params with jersey-media-moxy?如何使用 jersey-media-moxy 映射/转换嵌套参数?
【发布时间】:2015-06-02 15:56:31
【问题描述】:

我正在使用 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() {};
}

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

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

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

控制台输出结果为:

peter
null

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

这是我的货币参数转换器:

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

【问题讨论】:

    标签: java json jersey jax-rs moxy


    【解决方案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;
    }
    

    【讨论】:

    • 太好了,感谢您的提示。我一直怀疑一定有像 XmlAdapter 这样的东西,但显然昨天搜索了错误的术语。是否可以选择将用于 JSON/MOXy 的 XmlAdapter 和用于球衣 @*Param 的 ParamConverter 组合起来?
    • 它们是用于不同事物的不同动物。避免冗余的一种方法是完全忘记ParamConverter,只使用these techniques 之一,并调用适配器中的静态方法之一。
    猜你喜欢
    • 2018-12-23
    • 1970-01-01
    • 2016-04-28
    • 1970-01-01
    • 2014-12-25
    • 1970-01-01
    • 2014-03-12
    • 1970-01-01
    • 2013-07-17
    相关资源
    最近更新 更多