Domanda

Ho un servizio JAX-RS REST implementato utilizzando Jersey. Una delle caratteristiche interessanti di JAX-RS / Jersey è la facilità con un POJO può essere trasformato in un servizio REST, semplicemente spruzzando poche annotazioni Java ... compreso un banalmente facile meccanismo per tradurre POJO a JSON -. Utilizzando le annotazioni JAXB

Ora, mi piacerebbe essere in grado di trarre vantaggio da questa funzionalità fresco JSON-ficare per scopi non-REST - mi piacerebbe essere in grado di serializzare solo alcuni di questi oggetti su disco, come testo JSON. Ecco un oggetto JAXB esempio, che avrei voluto per serializzare:

@XmlRootElement(name = "user")
public class UserInfoImpl implements UserInfo {

    public UserInfoImpl() {} 

    public UserInfoImpl(String user, String details) {
        this.user = user;
        this.details = details;
    }

    public String getUser() { return user; }
    public void setUser(String user) { this.user = user; }

    public String getDetails() { return details; }
    public void setDetails(String details) { this.details = details; }

    private String user;
    private String details;
}

Jersey può trasformare uno di questi in JSON, senza informazioni aggiuntive. Mi chiedo se Jersey ha esposto questa funzionalità nelle API per le esigenze come il mio? Ho avuto fortuna trovare finora ...

Grazie!

UPDATE 2009-07-09 : ho imparato che posso usare i fornitori di oggetto per quasi fare esattamente quello che voglio:

  @Context Providers ps;
  MessageBodyWriter uw = ps.getMessageBodyWriter(UserInfoImpl.class, UserInfoImpl.class, new Annotation[0], MediaType.APPLICATION_JSON_TYPE);

  uw.writeTo(....)

... Questo scrive l'oggetto come JSON a qualsiasi OutputStream, che sarebbe perfetto per me, ma posso solo ottenere presso i fornitori di oggetto utilizzando @Context da un oggetto @Component. Qualcuno sa come accedervi da un normale, non-annotato POJO? Grazie!

È stato utile?

Soluzione

Jersey utilizza un paio di quadri diversi a seconda che si utilizzi mappato (), badgerfish (), o) la notazione naturali (. Naturale è di solito quello la gente vuole. E questo è implementato utilizzando il processore Jackson JSON molto buono (e molto veloce) standalone, credo, che va da Object-> JAXB-> JSON. Tuttavia Jackson fornisce anche un proprio fornitore di JAX-RS di andare Object-> JSON diretta.

In realtà, hanno anche aggiunto il supporto per le annotazioni JAXB. Date un'occhiata a

http://wiki.fasterxml.com/JacksonJAXBAnnotations

Credo che sia in ultima analisi, ciò che si sta cercando. Jackson non oggetto <-> elaborazione JSON ... Jersey fa solo le chiamate per voi

Altri suggerimenti

Ecco un semplice breve esempio di utilizzo di JAXB per mappare gli oggetti a JSON (utilizzando Jackson):

http://ondra.zizka.cz/ stránky / programovani / java / JAXB-jSON-jackson-howto.texy

ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(pojoObject);

annotazioni JAXB funzionano bene durante la serializzazione in XML. Il problema principale è che JAXB non supporta le matrici vuote. Così, quando la serializzazione qualcosa di simile ...

List myArray = new ArrayList();

... a JSON tramite anottations JAXB tutti gli array vuoti diventano nulli invece di [].

Per risolvere questo problema si può solo serializzare i tuoi POJO direttamente a JSON tramite Jackson.

Date un'occhiata a questo dal manuale d'uso di Jersey: http://jersey.java.net/nonav/documentation/latest /user-guide.html#d0e1959

Questo è il modo migliore per utilizzare provider di Jackson senza JAXB. Inoltre, si può sempre utilizzare l'ultima versione di Jackson da downlaoding jackson-all-x.y.z-jar dalla sua tela.

Questo metodo non interferire con le annotazioni JAXB dunque consiglio per avere una prova!

Poiché Jersey è un'implementazione di riferimento di JAX-RS e JAX-RS è focalizzata completamente sul fornire un modo standard di attuare il punto finale per il servizio REST i problemi di serializzazione payload è lasciato ad altri standard.

Credo che se hanno incluso la serializzazione oggetto che rientri nelle JAX-RS di serie sarebbe diventata rapidamente una grande bestia a più teste che sarebbe difficile da implementare e perdere alcuni di essi di messa a fuoco.

Mi rendo conto di come si è concentrato sulla realizzazione Jersey è pulita e semplice da usare endpoint REST. Nel mio caso ho appena sottoclasse un genitore che ha tutto l'impianto idraulico JAXB in esso gli oggetti in modo di smistamento tra binari e XML è molto pulito.

Con un po 'di bootstrap specifica Jersey, è possibile utilizzarlo per creare gli oggetti JSON necessarie per voi. È necessario includere le seguenti dipendenze (si può usare bundle, ma sarà causare problemi se si sta utilizzando per il test di saldatura):

    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-json</artifactId>
        <version>1.12</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-client</artifactId>
        <version>1.12</version>
    </dependency>

Da lì si può creare una classe JAXB annotata. Quanto segue è un esempio:

@XmlRootElement
public class TextMessage {
private String text;
    public String getText() { return text; }
    public void setText(String s) { this.text = text; }
}

Quindi è possibile creare la seguente unit test:

    TextMessage textMessage = new TextMessage();
    textMessage.setText("hello");
    textMessage.setUuid(UUID.randomUUID());

    // Jersey specific start
    final Providers ps = new Client().getProviders();
    // Jersey specific end
    final MultivaluedMap<String, Object> responseHeaders = new MultivaluedMap<String, Object>() {

        @Override
        public void add(final String key, final Object value) {
        }

        @Override
        public void clear() {
        }

        @Override
        public boolean containsKey(final Object key) {
            return false;
        }

        @Override
        public boolean containsValue(final Object value) {
            return false;
        }

        @Override
        public Set<java.util.Map.Entry<String, List<Object>>> entrySet() {
            return null;
        }

        @Override
        public List<Object> get(final Object key) {
            return null;
        }

        @Override
        public Object getFirst(final String key) {
            return null;
        }

        @Override
        public boolean isEmpty() {
            return false;
        }

        @Override
        public Set<String> keySet() {
            return null;
        }

        @Override
        public List<Object> put(final String key, final List<Object> value) {
            return null;
        }

        @Override
        public void putAll(
                final Map<? extends String, ? extends List<Object>> m) {
        }

        @Override
        public void putSingle(final String key, final Object value) {
        }

        @Override
        public List<Object> remove(final Object key) {
            return null;
        }

        @Override
        public int size() {
            return 0;
        }

        @Override
        public Collection<List<Object>> values() {
            return null;
        }
    };

    final MessageBodyWriter<TextMessage> messageBodyWriter = ps
            .getMessageBodyWriter(TextMessage.class, TextMessage.class,
                    new Annotation[0], MediaType.APPLICATION_JSON_TYPE);
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    Assert.assertNotNull(messageBodyWriter);

    messageBodyWriter.writeTo(textMessage, TextMessage.class,
            TextMessage.class, new Annotation[0],
            MediaType.APPLICATION_JSON_TYPE, responseHeaders, baos);
    final String jsonString = new String(baos.toByteArray());
    Assert.assertTrue(jsonString.contains("\"text\":\"hello\""));

Il vantaggio di questo approccio è che mantiene tutto all'interno della API JEE6, non librerie esterne sono esplicitamente necessari ad eccezione per i test e ottenere i fornitori. Tuttavia, è necessario creare un'implementazione di MultivaluedMap poiché non v'è nulla di previsto nella norma e che in realtà non lo usate. E ' possono essere anche più lento di GSON, e molto più complicato del necessario.

Capisco viste XML ma sarebbe mostrato qualche accortezza di richiedere il supporto JSON per POJO come equipaggiamento standard. Avendo a medico su identificatori JSON con i caratteri speciali non ha senso se l'implementazione è JSON e il vostro cliente è un RIA JavaScript.

Inoltre, non è che Java Beans NON sono POJO. Vorrei usare qualcosa di simile sulla superficie esterna del mio livello Web:

public class Model
{
   @Property height;
   @Property weight;
   @Property age;
}

No costruttore di default, non getter / setter rumore, solo un POJO con i miei annotazioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top