Question

J'ai un service JAX-RS REST mis en œuvre à l'aide de Jersey. L'une des fonctionnalités intéressantes de JAX-RS / Jersey est la facilité avec laquelle un POJO peut être transformé en un service REST, simplement en saupoudrant quelques annotations Java ... y compris un mécanisme trivialement facile pour traduire POJO à JSON -. Utilisant des annotations JAXB

Maintenant, je voudrais pouvoir profiter de cette fonctionnalité fraîche JSON-ification à des fins non-REST - J'aimerais pouvoir juste sérialisation certains de ces objets sur le disque, sous forme de texte JSON. Voici un exemple objet JAXB que je veux sérialisation:

@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 peut transformer l'un de ceux-ci en JSON sans informations supplémentaires. Je me demande si Jersey a exposé cette fonctionnalité dans l'API pour les besoins comme le mien? Je n'ai pas eu la chance de trouver jusqu'à présent ...

Merci!

Mise à jour 2009-07-09 : Je l'ai appris que je peux utiliser les fournisseurs objet presque fais exactement ce que je veux:

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

  uw.writeTo(....)

... Cela écrit l'objet JSON à tout outputstream, ce qui serait parfait pour moi, mais je ne peux obtenir les fournisseurs objet à l'aide d'un objet @Context @component. Est-ce que quelqu'un sait comment y accéder à partir d'un POJO régulier, non annotée? Merci!

Était-ce utile?

La solution

Jersey utilise un couple différents cadres selon que vous utilisez cartographié (), badgerfish (), ou notation naturelle (). Naturel est généralement celui des gens veulent. Et c'est mis en œuvre en utilisant le très bon (et très rapide) autonome Jackson processeur JSON, je crois, qui va de Object-> JAXB-> JSON. Cependant Jackson fournit également son propre fournisseur JAX-RS pour aller JSON Object- directe>.

En fait, ils ont même ajouté le support des annotations JAXB. Jetez un coup d'oeil à

http://wiki.fasterxml.com/JacksonJAXBAnnotations

Je pense que ce en fin de compte ce que vous recherchez. Jackson n'objet <-> traitement JSON ... Jersey fait que les appels pour vous

Autres conseils

Voici un exemple simple brève d'utiliser JAXB pour cartographier les objets à JSON (en utilisant Jackson):

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

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

annotations JAXB fonctionnent correctement lors de la sérialisation XML. Le principal problème est que JAXB ne supporte pas les tableaux vides. Alors, quand sérialisation quelque chose comme ça ...

List myArray = new ArrayList();

... à JSON via JAXB anottations tous vos tableaux vides deviennent nuls au lieu de [].

Pour résoudre cela, vous pouvez simplement sérialiser vos POJO directement à JSON via jackson.

Jetez un oeil à ce guide de l'utilisateur de Jersey: http://jersey.java.net/nonav/documentation/latest /user-guide.html#d0e1959

Ceci est la meilleure façon d'utiliser le fournisseur Jackson sans JAXB. De plus, vous pouvez toujours utiliser la dernière version de jackson par downlaoding jackson-all-x.y.z-pot de sa toile.

Cette méthode ne pas interférer avec vos annotations JAXB je vous conseille donc d'avoir essayer!

Depuis Jersey est une implémentation de référence de JAX-RS et JAX-RS se concentre entièrement sur la fourniture d'un moyen standard de mise en œuvre du point final pour le service REST les problèmes de sérialisation la charge utile est laissée à d'autres normes.

Je pense que si elles comprenaient la sérialisation d'objets dans les JAX-RS standard, il deviendrait rapidement une grande bête à plusieurs têtes qui serait difficile à mettre en œuvre et perdre une partie de son foyer.

J'apprécie la façon dont est axée sur la prestation Jersey propre et simple à utiliser points d'extrémité REST. Dans mon cas, je viens de sous-classé un parent qui a toute la plomberie JAXB en elle des objets de façon binaire et entre triages XML est très propre.

Avec un peu de Jersey bootstrapping spécifique, vous pouvez l'utiliser pour créer les objets JSON nécessaires pour vous. Vous devez inclure les dépendances suivantes (vous pouvez utiliser ensemble, mais il causera des problèmes si vous utilisez de soudure pour le test):

    <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à, vous pouvez créer une classe annotée JAXB. Voici un exemple:

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

Ensuite, vous pouvez créer le test unitaire suivant:

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

L'avantage de cette approche est qu'il conserve tout au sein de l'API JEE6, pas de bibliothèques externes sont explicitement nécessaires, sauf pour les tests et obtenir les fournisseurs. Cependant, vous devez créer une implémentation de MultivaluedMap puisqu'il n'y a rien prévu dans la norme et nous ne l'utilisez pas réellement. Il peut aussi être plus lent que GSON, et beaucoup plus compliqué que nécessaire.

Je comprends les vues XML, mais il aurait montré une certaine prévoyance besoin d'un soutien de JSON pour POJO en tant qu'équipement standard. Avoir au médecin des identificateurs de JSON avec des caractères spéciaux n'a pas de sens si l'implémentation est JSON et votre client est un JavaScript RIA.

En outre, pas que Java Les haricots sont pas POJO. Je voudrais utiliser quelque chose comme ceci sur la surface extérieure de mon niveau Web:

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

Aucun constructeur par défaut, pas de bruit de lecture / définition, juste un POJO avec mes propres annotations.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top