我从一个使用和产生JSON输出的服务开始。我使用resteasy-jackson-Provider进行(de)编组,它从类描述中获取信息。过了一会儿,我被要求将XML添加为MediaType。所以我用JAXB注释注释了我的DTO,并添加了resteasy-jaxb-Provider。结果,我观察到生成的JSON输出来自不同于原始格式的JAXB注释。
我在RestEasy版本3.0.4上。如上所述,我使用以下提供程序
我意识到这个问题,当我
>
XmlElementWrapper
用于列表和何时我编写了一个自定义的XmlAdapter
它序列化了一个复杂的数据结构Map
org.codehaus.jackson.map. exc.Un可识别的属性异常:无法识别的字段客户(类x.y.z.OptionalParametersMapType),在[源:org.apache.catalina.connector.CoyoteInputStream@77119553;行:1,列:131]处未标记为可忽略(通过引用链:x.y.z.Request["可选"]-
那么,如何防止RestEasy使用JAXB注释编组JSON?
这是请求类:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "domainRecommendationRequest")
public class Request {
@XmlJavaTypeAdapter(OptionalParametersXmlAdapter.class)
private Map<String, List<String>> optional = new HashMap<>();
}
这是XmlAdapter:
@Override
public class OptionalParametersXmlAdapter extends XmlAdapter<OptionalParametersMapType, Map<String, List<String>>> {
public OptionalParametersMapType marshal(Map<String, List<String>> v) throws Exception {
OptionalParametersMapType result = new OptionalParametersMapType();
List<OptionalParameterItemType> optionalParameterItemTypes = new ArrayList<>();
Set<String> keySet = v.keySet();
for (String parameterName : keySet) {
OptionalParameterItemType item = new OptionalParameterItemType();
item.name = parameterName;
item.values = v.get(parameterName);
optionalParameterItemTypes.add(item);
}
result.parameter = optionalParameterItemTypes;
return result;
}
}
这是地图的包装:
public class OptionalParametersMapType {
public List<OptionalParameterItemType> parameter = new ArrayList<>();
}
这是实际的地图条目:
public class OptionalParameterItemType {
@XmlAttribute
public String name;
@XmlElementWrapper(name = "values")
@XmlElement(name = "value")
public List<String> values = new ArrayList<>();
}
这就是我在JSON请求中所期望的:
{"optional":{"customer":["Mike"]}}
如你所见,我确实打算在XML中采用不同的格式。
问题是resteasy-jackson-Provider
依赖于jackson-module-jaxb-注解
,它用于将JAXB注解/注解类映射到JSON。现在在正常显式使用ObjectMapper
时,为了使用这个模块,我们需要显式注册这个模块,例如(参见此处)
ObjectMapper objectMapper = new ObjectMapper();
JaxbAnnotationModule module = new JaxbAnnotationModule();
objectMapper.registerModule(module);
-- OR --
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
objectMapper.setAnnotationIntrospector(introspector);
话虽如此,似乎(没有任何事实证实,但看起来很可能)当为您的序列化创建ObjectMapper
时,当注意到JAXB注释时,模块会自动注册。
我不知道我们可以使用任何可能的注释来阻止这种情况,但解决此问题的一种方法是为ObjectMapper
创建一个ContextResolver
,我们不注册JAXB模块。
@Provider
public class ObjectMapperContextResolver
implements ContextResolver<ObjectMapper> {
@Override
public ObjectMapper getContext(Class<?> type) {
return new ObjectMapper();
}
}
一旦我们将其注册到我们的JAXRS应用程序中,它将成为用于获取ObjectMapper
的上下文解析器。我们可以进一步配置ObjectMapper
,但这只是一个示例。测试它,它按预期工作。