与JaxRS和Jackson的多态性

时间:2017-11-03 14:23:26

标签: java java-ee jackson jax-rs

我有class Admin extends User {}AdminUser都延伸@XmlRootElement

@XmlRootElement
public class User {
   ....
}

@XmlRootElement
public class Admin extends User {

    String statement;
}

我将这个Json发送到正确的JaxRS服务:

{
    "id": "84",
    "content": "blablah",
    "user": {
        "id": 1,
        "email": "nicolas@robusta.io",
        "name": "Nicolas",
        "male": true,
        "admin": true,
        "statement":"hello world"
    }
}

这是Web服务。该评论应该有User,但我们这里有一个管理员,statement字段不为User

@POST
@Path("{id}/comments")
public Response createComment(@PathParam("id") long topicId, Comment comment) { ... }
杰克逊不接受Comment作为Comment,因为其UserAdmin

@XmlRootElement
public class Comment {
    String id;  
    String content;
    User user = null;
}

我应该如何告诉杰克逊接受任何类型的用户?如何做到最兼容Java EE(即使用具有另一个Json处理程序的服务器)?

1 个答案:

答案 0 :(得分:1)

使用多态对象的jackson方法是在json中添加一些额外的字段并使用(function() { var obj = { fn: function(a) { var f = v=> { debugger; console.log("Arguments length " + arguments.length); }; return f(a, 6, 7, 8); } }; obj.fn(1); } )(); 如果你可以将你的json更改为

@JsonTypeInfo

然后你可以简单地使用

"user": {
     "type": "Admin",
     ...
 }

如果你不能改变你的json,那么事情会变得复杂,因为没有默认的方法来处理这种情况,你必须编写自定义反序列化器。基本的简单案例看起来像这样:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(name = "User", value = User.class),
        @JsonSubTypes.Type(name = "Admin", value = Admin.class)
})
static class User {
    public String id;
}

您可以在ObjectMapper上注册

public static class PolymorphicDeserializer extends JsonDeserializer<User> {
    ObjectMapper mapper = new ObjectMapper();

    @Override
    public User deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        JsonNode tree = p.readValueAsTree();

        if (tree.has("statement")) // <= hardcoded field name that Admin has
            return mapper.convertValue(tree, Admin.class);

        return mapper.convertValue(tree, User.class);

    }
}

或带注释:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(User.class, new PolymorphicDeserializer());
mapper.registerModule(module);