这是关于一个带有JSON对象的REST PUT调用,它带有一个根元素,比如说:
{"place":
{"name":"Here",
"address":
{"address":"somewhere under the rainbow",
"city":
{"name":"Oz",
"country":
{"name":"Oz",
"zone":"Far Far Away"}
}
}
}
}
使用Jaxb Annotations定义
@XmlRootElement
public class PlaceOffline extends GlobalElement {
@XmlElement
public Address address;
}
,超类是
@XmlRootElement
public class GlobalElement implements Serializable {
@XmlElement
public Integer id;
@XmlElement
public String name;
@XmlElement
public String uniqueLabel;
}
我写了一个客户端,并且很可能用
失败了 com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "placeOffline"
然后我决定记录调用并创建一个ContainerRequestFilter来执行此操作
@Provider
public class RestLogFilter implements ContainerRequestFilter {
private Logger LOGGER_filter = Logger.getLogger(RestLogFilter.class.getName());
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
if (!MediaType.APPLICATION_JSON_TYPE.equals(requestContext.getMediaType())
|| requestContext.getEntityStream() == null) {
return;
}
InputStream inputStream = requestContext.getEntityStream();
byte[] bytes = IOUtils.readFully(inputStream , -1, true);
LOGGER_filter.info("Posted: " + new String(bytes, "UTF-8"));
requestContext.getEntityStream().mark(0);
}
}
然后猜猜是什么?
出乎意料地工作了!没有更多的错误。实体的打印解决了这个问题。别扭。
我认为它就像一个解决方法而且让我烦恼一点,有人解释一下吗?一种更优雅的方法来解决这个问题?
我正在使用WildFly 8.2
编辑:
它适用于
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
private final ObjectMapper mapper;
public ObjectMapperContextResolver() {
mapper = new ObjectMapper();
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
答案 0 :(得分:1)
你需要将Jackson添加到应用程序中(只是为了编译),因为你需要它的一些类。 Wildfly使用Jackson来反序列化JSON,并且当它看到未在POJO中建模的JSON上的属性时,默认行为将失败。例如以下JSON
{"firstName": "stack", "lastName": "overflow"}
有一个属性"lastName"
,它不在以下POJO
public class Person {
private String firstName;
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getFirstName() { return firstName; }
}
因此杰克逊的默认行为会失败。
对于依赖项,您可以添加
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>3.0.9.Final</version>
<scope>provided</scope>
</dependency>
注意provided
范围,因为Wildfly已经具有此依赖关系。如果您不使用Maven,那么您所需要的只是jackson-databind
和jacskon-annotations
。只需抓住2.4.x版本。如果您正在使用Jars,那么这些罐子不会与您的战争打包在一起非常重要,因为该版本可能与Wildfly已有的相冲突。
现在,如果你想忽略这个类的未知属性,你可以给我们一个类的注释
@JsonIgnoreProperties(ignoreUnknown = true)
public class PlaceOffline extends GlobalElement {
或者,如果要全局配置此行为,可以看到this answer。如何配置ObjectMapper
取决于以下内容
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
如果失败是由于JSON被包装的事实,例如
{"person": {"firstName": "stack", "lastName": "overflow"}}
然后你需要设置属性
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
这样做的目的是在类上注释的@XmlRootElement(name="person")
或@JsonRootName("person")
中查找类名的值。对于JAXB注释支持,您仍需要配置JAXB注释模块
mapper.registerModule(new JaxbAnnotationModule());
此模块包含在jackson-module-jaxb-annotations
jar中。如果您使用Maven(具有上述依赖性),它已被拉入。