Frage

Ich bin Jersey mit einem REST Web-Service für eine Server-Komponente zu erstellen.

Das JAXB-kommentierten Objekt, das ich wie diese in einer Liste sieht serialisiert werden soll:

@XmlRootElement(name = "distribution")
@XmlType(name = "tDistribution", propOrder = {
    "id", "name"
})
public class XMLDistribution {
    private String id;
    private String name;
    // no-args constructor, getters, setters, etc
}

Ich habe eine REST-Ressource eine Verteilung abzurufen, die wie folgt aussieht:

@Path("/distribution/{id: [1-9][0-9]*}")
public class RESTDistribution {
    @GET
    @Produces("application/json")
    public XMLDistribution retrieve(@PathParam("id") String id) {
        return retrieveDistribution(Long.parseLong(id));
    }
    // business logic (retrieveDistribution(long))
}

Ich habe auch eine REST-Ressource eine Liste aller Verteilungen abzurufen, die wie folgt aussehen:

@Path("/distributions")
public class RESTDistributions {
    @GET
    @Produces("application/json")
    public List<XMLDistribution> retrieveAll() {
        return retrieveDistributions();
    }
    // business logic (retrieveDistributions())
}

Ich verwende eine ContextResolver JAXB Serialisierung anpassen, die derzeit wie folgt konfiguriert ist:

@Provider
@Produces("application/json")
public class JAXBJSONContextResolver implements ContextResolver<JAXBContext> {
    private JAXBContext context;
    public JAXBJSONContextResolver() throws Exception {
        JSONConfiguration.MappedBuilder b = JSONConfiguration.mapped();
        b.nonStrings("id");
        b.rootUnwrapping(true);
        b.arrays("distribution");
        context = new JSONJAXBContext(b.build(), XMLDistribution.class);
    }
    @Override
    public JAXBContext getContext(Class<?> objectType) {
        return context;
    }
}

Sowohl REST-Ressourcen arbeiten, sowie die Kontext-Resolver. Dies ist ein Beispiel der Ausgabe für die ersten:

// path: /distribution/1
{"id":1,"name":"Example Distribution"}

Was genau ist es, was ich will. Dies ist ein Beispiel der Ausgabe für die Liste:

// path: /distributions
{"distribution":[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]}

Was nicht ganz ist, was ich will.

Ich verstehe nicht, warum es eine umschließende distribution Tag ist da. Ich wollte es mit .rootUnwrapping(true) im Zusammenhang mit Resolver entfernen, aber offensichtlich, dass nur entfernt einen anderen umschließenden Tag. Dies ist die Ausgabe mit .rootUnwrapping(false):

// path: /distribution/1
{"distribution":{"id":1,"name":"Example Distribution"}} // not ok
// path: /distributions
{"xMLDistributions":{"distribution":[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]}}

ich auch configure .arrays("distribution") musste immer ein JSON-Array zu erhalten, auch mit nur einem Element.

Idealerweise möchte ich diese haben als Ausgang:

// path: /distribution/1
{"id":1,"name":"Example Distribution"} // currently works
// path: /distributions
[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]

Ich habe versucht, einen List<XMLDistribution> zurückzukehren, einen XMLDistributionList (Wrapper um eine Liste), ein XMLDistribution[], aber ich konnte nicht einen Weg finden, einen einfachen JSON-Array von Verteilungen in meinem gewünschten Format zu erhalten.

Ich habe auch versucht, die andere von JSONConfiguration.natural() zurück Notationen, JSONConfiguration.mappedJettison(), etc, und konnte nicht so etwas wie, was ich brauche.

Wer weiß, wenn es möglich ist, JAXB zu konfigurieren, dies zu tun?

War es hilfreich?

Lösung

ich eine Lösung gefunden: Ersetzen Sie den JAXB JSON Serializer mit einem besseren erzogene JSON Serializer wie Jackson. Der einfache Weg ist jackson-jaxrs zu verwenden, die bereits für Sie getan hat. Die Klasse ist JacksonJsonProvider. Alles, was Sie tun müssen, ist Ihr Projekt web.xml bearbeiten, so dass Jersey (oder eine andere Implementierung JAX-RS) für sie durchsucht. Hier ist, was Sie hinzufügen müssen:

<init-param>
  <param-name>com.sun.jersey.config.property.packages</param-name>
  <param-value>your.project.packages;org.codehaus.jackson.jaxrs</param-value>
</init-param>

Und das ist alles, was es ist. Jackson wird für JSON Serialisierung verwendet werden, und es funktioniert so, wie Sie für Listen und Arrays erwarten.

Je länger Weg ist, Ihre eigenen MessageBodyWriter registriert schreiben „application / json“ zu produzieren. Hier ein Beispiel:

@Provider
@Produces("application/json")
public class JsonMessageBodyWriter implements MessageBodyWriter {
    @Override
    public long getSize(Object obj, Class type, Type genericType,
            Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    @Override
    public boolean isWriteable(Class type, Type genericType,
            Annotation annotations[], MediaType mediaType) {
        return true;
    }

    @Override
    public void writeTo(Object target, Class type, Type genericType,
            Annotation[] annotations, MediaType mediaType,
            MultivaluedMap httpHeaders, OutputStream outputStream)
            throws IOException {        
        new ObjectMapper().writeValue(outputStream, target);
    }
}

Sie müssen sicherstellen, dass Ihr web.xml enthält das Paket, wie sie für die fertige Lösung oben.

So oder so: voila! Sie werden sehen, JSON richtig gebildet wird.

Sie können Jackson hier herunterladen: http://jackson.codehaus.org/

Andere Tipps

Die Antwort von Jonhatan groß ist, und es war für mich sehr nützlich.

Nur ein Upgrade:

Wenn Sie die Version 2.x von Jackson verwenden (zum Beispiel Version 2.1) die Klasse com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider daher die web.xml ist:

<init-param>
  <param-name>com.sun.jersey.config.property.packages</param-name>
  <param-value>your.project.packages;com.fasterxml.jackson.jaxrs.json</param-value>
</init-param>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top