2017-11-03 2 views
0

Ich habe class Admin extends User {}. Admin und User beide erstreckt @XmlRootElementPolymorphismus mit JaxRS und Jackson

@XmlRootElement 
public class User { 
    .... 
} 

@XmlRootElement 
public class Admin extends User { 

    String statement; 
} 

ich diesen Json Dienst nach rechts JaxRS schicke:

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

Hier ist der Web-Service. Der Kommentar soll eine User haben, aber wir haben hier einen Admin, der ein statement unbekanntes Feld User hat.

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

Comment nicht als Comment von Jackson akzeptiert, weil seine User ein Admin ist:

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

Wie soll ich Jackson sagen, jede Art von Benutzer zu akzeptieren? Wie funktioniert das am besten mit Java EE kompatibel (dh mit Servern, die einen anderen Json-Handler haben)?

+0

Versuchten Sie @XmlElement (name = „user ", type = Admin.class) in der Kommentarklasse –

+0

Es ist nicht immer ein Admin. Ein Benutzer oder Administrator kann einen Kommentar erstellen –

Antwort

1

Der jackson Ansatz mit polymorphen Objekten ist etwas zusätzliches Feld in Ihrem json hinzuzufügen und @JsonTypeInfo verwenden Wenn Sie Ihr json zu so etwas wie

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

Dann können Sie einfach

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

verwenden ändern

Wenn Sie Ihren JSON nicht ändern können, können die Dinge kompliziert werden, da es keine Standardmethode gibt, um einen solchen Fall zu behandeln, und Sie müssen benutzerdefinierte Deserialisierung schreiben r. Und Basis einfacher Fall würde wie folgt aussehen:

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

    } 
} 

Sie es auf ObjectMapper registrieren

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

oder mit Anmerkung:

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