Java 与JaxRS和Jackson的多态性

Java 与JaxRS和Jackson的多态性,java,jakarta-ee,jackson,jax-rs,Java,Jakarta Ee,Jackson,Jax Rs,我有类管理员扩展用户{}Admin和User都扩展了@XmlRootElement @XmlRootElement public class User { .... } @XmlRootElement public class Admin extends User { String statement; } 我将此Json发送到正确的JaxRS服务: { "id": "84", "content": "blablah", "user": {

我有
类管理员扩展用户{}
Admin
User
都扩展了
@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服务。注释应该有一个
用户
,但我们这里有一个管理员,他有一个
语句
字段,而
用户
不知道该字段

@POST
@Path("{id}/comments")
public Response createComment(@PathParam("id") long topicId, Comment comment) { ... }
杰克逊不接受
评论
作为
评论
,因为其
用户
管理员

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

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

使用多态对象的jackson方法是在Json中添加一些附加字段,如果可以将Json更改为

"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,那么事情可能会变得复杂,因为没有默认的方法来处理这种情况,您必须编写自定义反序列化程序。基本的简单情况如下所示:

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);

    }
}
或带有注释:

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

使用多态对象的jackson方法是在json中添加一些附加字段,如果可以将json更改为

"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,那么事情可能会变得复杂,因为没有默认的方法来处理这种情况,您必须编写自定义反序列化程序。基本的简单情况如下所示:

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);

    }
}
或带有注释:

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

您是否在注释Classic中尝试了@XmlElement(name=“user”,type=Admin.class)它并不总是管理员。用户或管理员可以创建注释。您是否在注释类中尝试了@xmlement(name=“User”,type=Admin.class)它并不总是管理员。用户或管理员可以创建注释