web-dev-qa-db-fra.com

Jersey / JAX-RS: renvoyer une carte au format XML / JSON

La façon de renvoyer un Map en tant que document XML/JSON en utilisant le framework Jersey/JAX-RS n'est pas si évidente. Il prend déjà en charge Lists, mais quand il s'agit de Maps, il n'y a pas de MessageBodyWriter. Et même si je devais intégrer le Ma dans une classe wrapper, il n'y a pas de type map dans le schéma XML.

Des conseils pratiques sur la façon de marshaler une carte dans un document XML/JSON à Jersey?

20
ktm5124

Je sais qu'il est très tard pour répondre, mais j'espère que cela aidera quelqu'un un jour :) La solution la plus simple et la plus rapide que j'ai appliquée est

@GET
@Path("/{messageId}")
@Produces(MediaType.APPLICATION_JSON)
public Response getMessage(@PathParam("messageId") long id) {
    Map<String, String> map = new HashMap<>();
    map.put("1", "abc");
    map.put("2", "def");
    map.put("3", "ghi");

    return Response.status(Status.OK).entity(map).build();
}

Sortie: {"1": "abc", "2": "def", "3": "ghi"}

Cela devrait certainement vous aider à résoudre votre problème.

8
NoisyBoy

Il est très facile de le faire dans Java EE 7.

La classe de ressources REST:

package com.mycompany.maptojson.rest;

import Java.util.HashMap;
import Java.util.Map;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.enterprise.context.RequestScoped;

@Path("maps")
@RequestScoped
public class MapToJson {

    @GET
    @Produces("application/json")
    public Map getJson() {
       Map<String, String> theMap = new HashMap<>();
       theMap.put("foo", "bar");
       return theMap;
    }
}

Application:

package com.mycompany.maptojson.rest;

import Java.util.Set;
import javax.ws.rs.core.Application;

@javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new Java.util.HashSet<>();
        // following code can be used to customize Jersey 2.0 JSON provider:
        try {
            Class jsonProvider = Class.forName("org.glassfish.jersey.jackson.JacksonFeature");
            // Class jsonProvider = Class.forName("org.glassfish.jersey.moxy.json.MoxyJsonFeature");
            // Class jsonProvider = Class.forName("org.glassfish.jersey.jettison.JettisonFeature");
            resources.add(jsonProvider);
        } catch (ClassNotFoundException ex) {
            Java.util.logging.Logger.getLogger(getClass().getName()).log(Java.util.logging.Level.SEVERE, null, ex);
        }
        addRestResourceClasses(resources);
        return resources;
    }

    private void addRestResourceClasses(Set<Class<?>> resources) {
        resources.add(com.mycompany.maptojson.rest.MapToJson.class);
    }
}

Comme vous pouvez le voir, vous pouvez configurer différentes classes comme jsonProvider:

Class.forName("org.glassfish.jersey.jackson.JacksonFeature");

ou

Class.forName("org.glassfish.jersey.moxy.json.MoxyJsonFeature");

ou

Class.forName("org.glassfish.jersey.jettison.JettisonFeature");
7
user1907906

Je sais que cela fait déjà un moment, mais peut-être que quelqu'un le trouvera utile.

J'ai un problème similaire et pour moi il semble que seul Jackson supporte actuellement ce type de mappage direct de Map en JSON.

Dans Jersey , c'est aussi simple que de renvoyer la carte à partir de la méthode des ressources:

@Path("myResource")
public class MyResource {
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public Map<String, String> getMap() {
      Map<String, String> map = new HashMap<String, String>();
      map.put("some key", "some value");
      return map;
  }
}

et y accéder depuis le client en tant que:

// ... (client initialization)
Map<String, String> map = client.target().path("myResource").request("application/json").get(Map.class);

Avec Jackson (par opposition à MOXy ), vous devez enregistrer le JacksonFeature manuellement, par exemple dans votre javax.ws.rs.core.Application sous-classe (ou ResourceConfig dans Jersey ):

public class MyApp extends ResourceConfig {
  public MyApp() {
    super(MyResource.class, JacksonFeature.class);
  }
}

Et assurez-vous d'avoir le module Jersey Jackson sur classpath. Dans maven, ajoutez simplement:

<dependency>
  <groupId>org.glassfish.jersey.media</groupId>
  <artifactId>jersey-media-json-jackson</artifactId>
  <version>...</version>
</dependency>

sans maven, il pourrait être un peu plus compliqué d'ajouter toutes les dépendances. Et c'est tout, cela devrait fonctionner. Au moins avec Jackson provider.

Cela n'a pas fonctionné pour moi dans Jettison et id ne fonctionne pas dans MOXy encore (il y a un problème ouvert).

J'espère que cela t'aides.

6
AdamL

Par défaut, Jersey utilise le fournisseur MOXy XML/JSON. Donc, si vous souhaitez utiliser MOXy, vous devez ajouter un adaptateur séparé. La solution simple est de supprimer la dépendance MOXy de pom.xml et d'ajouter la dépendance Jackson. Jackson s'occupera de tout.

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>{latest version}</version>
</dependency>

Désolé, je ne sais pas pourquoi MOXy est le fournisseur par défaut de Jeresey.

public class BeanClass{
    private int duration, Id;
    private String description;
    private User user = new User();
    Map<String, String> map = new HashMap<>();
 }


@GET
@Produces({ MediaType.APPLICATION_JSON }) // , MediaType.APPLICATION_XML
public Response getAll() {
        List<BeanClass> lstBean = ...
        return Response.ok().entity(lstBean).build();
}

Merci,

1
Anudeep Abraham

La solution qui a fonctionné pour moi (Utilisation de largage):

@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getJson() {
    Map<String, String> testMap = new HashMap<>();
    testMap.put("Key1", "value1");
    testMap.put("key2", "value2");
    JSONObject obj = new JSONObject(testMap);

    return Response.status(200).entity(obj).build();
}
1
Benav