2017-05-02 50 views
7

Po pierwsze, zanim zdecydujesz się zamknąć moje pytanie, wypróbowałem rozwiązanie this, ale nie działa ono dla mnie.Nie można wygenerować poprawnie sformatowanego pliku XML i JSON w tym samym czasie.

Mam usługę REST, która ma zwrócić JSON lub XML w zależności od nagłówka Accept. Mogę go wygenerować właściwego JSON, ale nie XML. Kiedy naprawię XML, JSON zostaje wkręcony. Poniżej przedstawiam mój kod.

XML wydaje się dobre, ale JSON nie

Message.java

import java.util.List; 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlElementRef; 
import javax.xml.bind.annotation.XmlElementWrapper; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Message { 
    int id; 
    String text; 

    @XmlElementWrapper 
    @XmlElementRef 
    List<Comment> comments; 

    public Message() { 

    } 
    // getters and setters 
} 

Comment.java

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name = "comment") 
public class Comment { 
    int id; 
    String text; 

    public Comment() { 

    } 
    //getters and setters 
} 

MessageResource.java

import java.util.List; 

import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.Response; 


@Path("messages") 
public class MessageResource { 

    DBUtils db = new DBUtils(); 

    @GET 
    @Produces(MediaType.APPLICATION_XML) 
    public Response getXML() { 
     List<Message> messages = db.getMessages(); 
     return Response.ok(messages.toArray(new Message[messages.size()]), MediaType.APPLICATION_XML).build(); 
    } 

    @GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public Response getJSON() { 
     List<Message> messages = db.getMessages(); 
     return Response.ok(messages.toArray(new Message[messages.size()]), MediaType.APPLICATION_JSON).build(); 
    } 
} 

Oto wynik XML, która jest OK:

<messages> 
    <message> 
     <id>1</id> 
     <text>Java is an OOP language.</text> 
     <comments> 
      <comment> 
       <id>20</id> 
       <text>That's correct.</text> 
      </comment> 
      <comment> 
       <id>30</id> 
       <text>test test</text> 
      </comment> 
     </comments> 
    </message> 
    <message> 
     <id>1</id> 
     <text>Java is an OOP language.</text> 
     <comments> 
      <comment> 
       <id>20</id> 
       <text>That's correct.</text> 
      </comment> 
      <comment> 
       <id>30</id> 
       <text>test test.</text> 
      </comment> 
     </comments> 
    </message> 
</messages> 

A oto wynik JSON zwrócić uwagę na comments. Potrzebuję tylko tablicy comments.

[ 
    { 
    "id": 1, 
    "text": "Java is an OOP language.", 
    "comments": { 
     "comment": [ 
     { 
      "id": 20, 
      "text": "That's correct." 
     }, 
     { 
      "id": 30, 
      "text": "test test" 
     } 
     ] 
    } 
    }, 
    { 
    "id": 1, 
    "text": "Java is an OOP language.", 
    "comments": { 
     "comment": [ 
     { 
      "id": 20, 
      "text": "That's correct." 
     }, 
     { 
      "id": 30, 
      "text": "test test." 
     } 
     ] 
    } 
    } 
] 

Mocowanie JSON bałagan odpowiedź XML

jeśli usunąć @XmlElementWrapper i @XmlElementRef adnotacje z klasy Message, to pracuje dla JSON, ale nie XML.

Message.jave

import java.util.List; 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Message { 
    int id; 
    String text; 

    List<Comment> comments; 

    public Message() { 

    } 
    //getters and setters 
} 

The Comment i MessageResource klas pozostają takie same.

Oto wyniki uzyskać:

JSON - OK

[ 
    { 
    "id": 1, 
    "text": "Java is an OOP language.", 
    "comments": [ 
     { 
     "id": 20, 
     "text": "That's correct." 
     }, 
     { 
     "id": 30, 
     "text": "test test" 
     } 
    ] 
    }, 
    { 
    "id": 1, 
    "text": "Java is an OOP language.", 
    "comments": [ 
     { 
     "id": 20, 
     "text": "That's correct." 
     }, 
     { 
     "id": 30, 
     "text": "test test." 
     } 
    ] 
    } 
] 

XML - ŹLE

<messages> 
    <message> 
     <id>1</id> 
     <text>Java is an OOP language.</text> 
     <comments> 
      <id>20</id> 
      <text>That's correct.</text> 
     </comments> 
     <comments> 
      <id>30</id> 
      <text>test test</text> 
     </comments> 
    </message> 
    <message> 
     <id>1</id> 
     <text>Java is an OOP language.</text> 
     <comments> 
      <id>20</id> 
      <text>That's correct.</text> 
     </comments> 
     <comments> 
      <id>30</id> 
      <text>test test.</text> 
     </comments> 
    </message> 
</messages> 

Czy ktoś wie, jak sprawić, by te dwie prace razem? Jedynym rozwiązaniem, które znalazłem, jest użycie JAXB dla XML i GSON dla JSON, ale muszę ręcznie tworzyć obiekty JSON za pomocą GSON.

Dzięki!

+0

Szukały do ​​[JacksonJaxbJSON] (http://fasterxml.github.io/jackson-jaxrs-json-provider/javadoc/2.0.1/com/ fasterxml/jackson/jaxrs/json/JacksonJaxbJsonProvider.html) adnotacje? jak 'JsonType' .. – ulab

+0

@ulab, czy możesz pokazać mi przykład użycia? Nie widziałem tego wcześniej. –

Odpowiedz

5

Proponowane przeze mnie rozwiązanie wykorzystuje JAXB do XML (jak ty). Ale dla JSON-a używa Jackson-JAXRS (w przeciwieństwie do ciebie), jak na przykład opisano w tym answer. Zamiast używać GSON, musisz użyć Jackson-JAXRS (na przykład z Maven). Aby uzyskać żądane wyjście XML i JSON, należy dostroić adnotacje właściwości List<Comment> comments w klasie Message.

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Message { 
    int id; 
    String text; 

    @XmlElementWrapper(name="comments") 
    @XmlElementRef 
    @JsonUnwrapped 
    List<Comment> comments; 

    //getters and setters 
} 

Przez @XmlElementRef dostać każdy Comment obiekt pisemnej jako element <comment>. Wreszcie, przez @XmlElementWrapper(name="comments") otrzymasz wszystkie te zawinięte w element <comments>.

Wyjście XML jest:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<messages> 
    <message> 
    <id>1</id> 
    <text>Java is an OOP language.</text> 
    <comments> 
     <comment> 
     <id>20</id> 
     <text>That's correct.</text> 
     </comment> 
     <comment> 
     <id>30</id> 
     <text>test test.</text> 
     </comment> 
    </comments> 
    </message> 
    <message> 
    <id>1</id> 
    <text>Java is an OOP language.</text> 
    <comments> 
     <comment> 
     <id>20</id> 
     <text>That's correct.</text> 
     </comment> 
     <comment> 
     <id>30</id> 
     <text>test test.</text> 
     </comment> 
    </comments> 
    </message> 
</messages> 

Przez @JsonUnwrapped (importowane z pakietu com.fasterxml.jackson.annotation) masz List<Comment> comments napisany jako zwykły tablicę obiektów.

Wyjście JSON jest:

[ 
    { 
    "id": 1, 
    "text": "Java is an OOP language.", 
    "comments": [ 
     { 
     "id": 20, 
     "text": "That's correct." 
     }, 
     { 
     "id": 30, 
     "text": "test test." 
     } 
    ] 
    }, 
    { 
    "id": 1, 
    "text": "Java is an OOP language.", 
    "comments": [ 
     { 
     "id": 20, 
     "text": "That's correct." 
     }, 
     { 
     "id": 30, 
     "text": "test test." 
     } 
    ] 
    } 
] 
+0

Dzięki! Twoje rozwiązanie produkuje poprawny kod XML i prawie poprawny JSON, z tym wyjątkiem, że tablica ma nazwę "komentarz", a nie "komentarze". Musiałem zmienić adnotację XML, aby działała. Użyłem tych adnotacji 'XMLElementWrapper (name =" comments ") @XMLElementRef @ JsonUnrwapped'. –

+0

@TurikMirash Dzięki za opinie! Zaktualizowałem swoją odpowiedź, poprawiając adnotacje XML. –