自定义对象在Jax-RS中反序列化很好但如果它在另一个对象中使用它不起作用

时间:2015-03-28 19:57:50

标签: java serialization glassfish jersey jax-rs

如果我只是通过

传递我的自定义对象,反序列化工作正常
@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);
    }
}

1 个答案:

答案 0 :(得分:1)

问题是所有其他对象的阅读器在解组时不进行查找/委派。我的意思可以在this answer中看到,其中一个读者根据类型查找另一个读者。假设格式为JSON,无论您使用的是MOXy(Glassfish的默认值)还是Jackson,结果都是一样的。读者非常聪明,可以自己处理JSON,因此不需要查找任何其他读者。

一种解决方案是为包装类创建另一个读取器,并进行查找/委派,如上面的链接所示。如果你有很多这些情况,你可以扩展默认阅读器,并覆盖它的解组方法,但我会完全反对这一点,除非你真的知道你在做什么。

根据您使用的序列化程序,另一种解决方案是编写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(){}
}

在这种情况下,根本不需要自定义阅读器。这将处理CustomObject和具有CustomObject成员的对象。这个问题的一个问题是我不确定你是如何获得InputStream的。您只需使用Jackson API来解析JSON。

如果您想使用Jackson而不是默认的玻璃鱼MOXy,您可以添加杰克逊依赖

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.13</version>
</dependency>

然后注册JacksonFeature,或者只是禁用MOXy,如上所述here。如果你想继续使用MOXy,我不知道是否有类级适配器这样的东西,所以你仍然需要读者以及为类成员创建XmlAdapter。这有点麻烦,但这就是为什么我推荐杰克逊,除了这个特殊的用例之外还有很多其他原因。您可以看到适配器here

的示例

现在很多答案都基于您使用JSON格式的假设,因为您尚未指定所使用的媒体类型。如果是其他格式,那么我想也许你唯一的解决方案是为包装器创建另一个客户读者。