自定义对象在 Jax-RS 中反序列化很好,但如果它在另一个对象中使用,则它不起作用
Custom object deserializes fine in Jax-RS but if it is used in another object it doesn't work
如果我只是将我的自定义对象传递给
,反序列化工作正常
@POST
public Response saveCustomObject(CustomObject data)
{
// Prints correct value
System.out.println(data);
}
但是,如果它是另一个对象上的属性,它只是获取我的自定义对象的默认值
@POST
public Response saveCustomObjectWrapper(CustomObjectWrapper data)
{
// Prints incorrect value
System.out.println(data.getCustomObject());
}
我的提供商已注册,如下所示:
public CustomObject readFrom(Class<CustomObject> type, Type type1, Annotation[] antns, MediaType mt, MultivaluedMap<String, String> mm, InputStream in) throws IOException, WebApplicationException
{
try {
return new CustomObject(IOUtils.toString(in));
} catch (Exception ex) {
throw new ProcessingException("Error deserializing a CustomObject.", ex);
}
}
问题是所有其他对象的 reader 在解组时不执行 lookup/delegation。我的意思是,可以在 中看到,其中一个 reader 根据类型查找另一个 reader。假设格式为 JSON,无论您使用的是 MOXy(Glassfish 的默认格式)还是 Jackson,结果都是一样的。 reader 足够聪明,可以自己处理 JSON,因此不需要查找任何其他 reader。
一个解决方案是为包装器 class 创建另一个 reader,然后执行 lookup/delegation,如上文 link 所示。如果你有很多这样的情况,你可以扩展默认 reader,并覆盖它的解组方法,但我完全不建议这样做,除非你真的知道你在做什么。
根据您使用的序列化器,另一种解决方案是编写 JsonDeserializer
(对于 Jackson)或 XmlAdapter
(对于 MOXy 或 Jackson)。对于杰克逊来说,一个例子是这样的(你可以看到一个更好的例子here)
public class CustomObjectDeserializer extends JsonDeserializer<CustomObject> {
@Override
public CustomObject deserialize(JsonParser jp, DeserializationContext dc)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
return new CustomObject("Hello World");
}
}
@JsonDeserialize(using = CustomObjectDeserializer.class)
public class CustomObject {
public String message;
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public CustomObject(String message) { this.message = message; }
public CustomObject(){}
}
在这种情况下,根本不需要自定义 reader。这将处理 CustomObject
和具有 CustomObject
作为成员的对象。一个问题是我不确定如何或是否可以得到 InputStream
。您只需要使用 Jackson API 来解析 JSON.
如果您想使用 Jackson 而不是 glassfish 的默认 MOXy,您只需添加 Jackson 依赖项
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.13</version>
</dependency>
然后注册 JacksonFeature
,或者简单地禁用 MOXy,如前所述 . If you want to continue using MOXy, I don't know if there is such thing as a class level adapter, so you will still need the reader as well as create a XmlAdapter
for class members. It's a bit of a hassle, but that's why I recommend Jackson, for many other reasons, besides this particular use case. You can see an example of an adapter
现在很多答案都是基于您使用 JSON 格式的假设,因为您没有指定您正在使用的媒体类型。如果是其他格式,那么我认为您唯一的解决方案可能是为包装器创建另一个客户 reader。
如果我只是将我的自定义对象传递给
,反序列化工作正常@POST
public Response saveCustomObject(CustomObject data)
{
// Prints correct value
System.out.println(data);
}
但是,如果它是另一个对象上的属性,它只是获取我的自定义对象的默认值
@POST
public Response saveCustomObjectWrapper(CustomObjectWrapper data)
{
// Prints incorrect value
System.out.println(data.getCustomObject());
}
我的提供商已注册,如下所示:
public CustomObject readFrom(Class<CustomObject> type, Type type1, Annotation[] antns, MediaType mt, MultivaluedMap<String, String> mm, InputStream in) throws IOException, WebApplicationException
{
try {
return new CustomObject(IOUtils.toString(in));
} catch (Exception ex) {
throw new ProcessingException("Error deserializing a CustomObject.", ex);
}
}
问题是所有其他对象的 reader 在解组时不执行 lookup/delegation。我的意思是,可以在
一个解决方案是为包装器 class 创建另一个 reader,然后执行 lookup/delegation,如上文 link 所示。如果你有很多这样的情况,你可以扩展默认 reader,并覆盖它的解组方法,但我完全不建议这样做,除非你真的知道你在做什么。
根据您使用的序列化器,另一种解决方案是编写 JsonDeserializer
(对于 Jackson)或 XmlAdapter
(对于 MOXy 或 Jackson)。对于杰克逊来说,一个例子是这样的(你可以看到一个更好的例子here)
public class CustomObjectDeserializer extends JsonDeserializer<CustomObject> {
@Override
public CustomObject deserialize(JsonParser jp, DeserializationContext dc)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
return new CustomObject("Hello World");
}
}
@JsonDeserialize(using = CustomObjectDeserializer.class)
public class CustomObject {
public String message;
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public CustomObject(String message) { this.message = message; }
public CustomObject(){}
}
在这种情况下,根本不需要自定义 reader。这将处理 CustomObject
和具有 CustomObject
作为成员的对象。一个问题是我不确定如何或是否可以得到 InputStream
。您只需要使用 Jackson API 来解析 JSON.
如果您想使用 Jackson 而不是 glassfish 的默认 MOXy,您只需添加 Jackson 依赖项
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.13</version>
</dependency>
然后注册 JacksonFeature
,或者简单地禁用 MOXy,如前所述 XmlAdapter
for class members. It's a bit of a hassle, but that's why I recommend Jackson, for many other reasons, besides this particular use case. You can see an example of an adapter
现在很多答案都是基于您使用 JSON 格式的假设,因为您没有指定您正在使用的媒体类型。如果是其他格式,那么我认为您唯一的解决方案可能是为包装器创建另一个客户 reader。