Pergunta

Eu tenho um serviço JAX-RS RESTO implementado usando Jersey. Um dos recursos interessantes do JAX-RS / Jersey é a facilidade com que um POJO pode ser transformado em um serviço REST, simplesmente por aspersão algumas anotações Java ... incluindo um mecanismo trivialmente fácil para traduzir POJOs para JSON -. Usando anotações JAXB

Agora, eu gostaria de ser capaz de tirar partido desta funcionalidade legal para fins não-Rest JSON-ifying - Eu adoraria ser capaz de simplesmente serializar alguns desses objetos para o disco, como texto JSON. Aqui está um objeto exemplo JAXB que eu gostaria de serialize:

@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 pode transformar um deles em JSON com nenhuma informação adicional. Eu estou querendo saber se Jersey expôs essa funcionalidade na API para as necessidades como a minha? Eu tive nenhuma sorte é tão longe ...

Obrigado!

Atualização 2009-07-09 : Eu aprendi que eu posso usar os provedores opor a quase fazer exatamente o que eu quero:

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

  uw.writeTo(....)

... Este escreve o objeto como JSON para qualquer outputstream, o que seria perfeito para mim, mas eu só posso chegar aos Provedores de objeto usando @Context de um objeto @Component. Alguém sabe como acessá-lo a partir de um POJO regular, un-anotada? Obrigado!

Foi útil?

Solução

Jersey usa um par de estruturas diferentes dependendo se você usar mapeada (), badgerfish (), ou notação naturais (). Natural é geralmente aquele que as pessoas querem. E que é implementado utilizando o muito bom (e muito rápido) standalone processador Jackson JSON, creio eu, que vai de Objeto-> JAXB-> JSON. No entanto Jackson também fornece seu próprio provedor JAX-RS para ir Objeto direto> JSON.

Na verdade, eles ainda acrescentou suporte para anotações JAXB. Ter um olhar para

http://wiki.fasterxml.com/JacksonJAXBAnnotations

Eu acho que é em última análise, o que você está procurando. Jackson faz objeto <-> Processamento de JSON ... Jersey só faz as chamadas para você

Outras dicas

Aqui está um exemplo simples breve do uso de JAXB para mapear objetos para JSON (usando Jackson):

http://ondra.zizka.cz/ stranky / programovani / java / jaxb-json-jackson-howto.texy

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

JAXB anotações funcionam bem quando a serialização de XML. O principal problema é que JAXB não suporta matrizes vazias. Então, quando a serialização de algo assim ...

List myArray = new ArrayList();

... para json via jaxb anottations todas as suas matrizes vazias tornam-se nulos em vez de [].

Para resolver isso, você pode simplesmente serializar seus pojos diretamente para json via jackson.

Dê uma olhada neste partir guia do usuário de Jersey: http://jersey.java.net/nonav/documentation/latest /user-guide.html#d0e1959

Esta é a melhor maneira de usar o provedor Jackson sem JAXB. Além disso, você sempre pode usar a versão mais recente de jackson por downlaoding jackson-all-x.y.z-jar de sua web.

Este método não irá interferir com suas anotações JAXB então eu sugiro para ter uma tentativa!

Desde Jersey é uma implementação de referência de JAX-RS e JAX-RS é focada completamente em fornecer uma maneira padrão de implementação do ponto final para o serviço REST as questões de serialização a carga é deixado para outras normas.

Eu acho que se eles incluíram serialização objeto nas JAX-RS padrão seria rapidamente tornar-se uma besta multi-headed grande que seria difícil de implementar e perder algum dele é foco.

I apreciar como focada Jersey é no fornecimento limpo e simples de endpoints uso REST. No meu caso eu tenho apenas uma subclasse um pai que tem todas as canalizações JAXB nele para mobilizar objetos entre binário e XML é muito limpo.

Com um pouco de bootstrapping específica Jersey, você pode usá-lo para criar os objetos JSON necessárias para você. Você precisa incluir as seguintes dependências (você pode usar pacote, mas vai causar problemas se você estiver usando Weld para testes):

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

De lá você pode criar uma classe JAXB anotado. O seguinte é um exemplo:

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

Em seguida, você pode criar o seguinte teste de unidade:

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

A vantagem dessa abordagem é que mantém tudo dentro da API JEE6, há bibliotecas externas são explicitamente necessário, exceto para testar e recebendo os fornecedores. No entanto, você precisa criar uma implementação de MultivaluedMap porque não há nada previsto na norma e nós realmente não usá-lo. É pode também ser mais lento do que Gson, e muito mais complicado do que o necessário.

Eu entendo visões XML mas teria mostrado alguma previsão para exigir apoio JSON para POJOs como equipamento standard. Tendo em médico até identificadores JSON com caracteres especiais não faz sentido se a sua implementação é JSON e seu cliente é uma RIA JavaScript.

Além disso, não que Java Beans não são POJOs. Eu gostaria de usar algo como isto na superfície externa do meu web níveis:

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

No construtor padrão, nenhum ruído getter / setter, apenas um POJO com as minhas próprias anotações.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top