与JaxRS和Jackson的多态性

与JaxRS和Jackson的多态性

本文介绍了与JaxRS和Jackson的多态性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有类管理员扩展用户{} 管理员用户两者都延伸 @XmlRootElement

I have class Admin extends User {}. Admin and User both extends @XmlRootElement

@XmlRootElement
public class User {
   ....
}

@XmlRootElement
public class Admin extends User {

    String statement;
}

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

I am sending this Json to the right JaxRS service:

{
    "id": "84",
    "content": "blablah",
    "user": {
        "id": 1,
        "email": "[email protected]",
        "name": "Nicolas",
        "male": true,
        "admin": true,
        "statement":"hello world"
    }
}

这是Web服务。评论应该有用户,但我们这里有一个管理员,其语句字段未知用户

Here is the Web service. The comment is supposed to have a User, but we have here an Admin that has a statement field unknown to User.

@POST
@Path("{id}/comments")
public Response createComment(@PathParam("id") long topicId, Comment comment) { ... }

评论不被Jackson接受为评论因为其用户管理员

Comment is not accepted as a Commentby Jackson because its User is an Admin:

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

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

How should I tell Jackson to accept any kind of User ? How to do that the most Java EE compatible (ie with servers that have another Json handler) ?

推荐答案

具有多态性的jackson方法对象是在你的json中添加一些额外的字段并使用 @JsonTypeInfo 如果你可以将你的json更改为类似

The jackson approach with polymorphic objects is to add some additional field in your json and use @JsonTypeInfo If you can change your json to something like

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

然后你可以简单地使用

@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;
}






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


If you can't change your json, then things can get complicated, because there is no default way to handle such a case and you will have to write custom deserializer. And base simple case would look something like this:

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上注册

You can register it on ObjectMapper

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

或带注释:

@JsonDeserialize(using = PolymorphicDeserializer.class)
class User {
    public String id;
}

这篇关于与JaxRS和Jackson的多态性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 04:19