Джерси/JAX-RS: верните карту в формате XML/JSON

Не так очевидно, как вернуть Map в качестве документа XML/JSON с использованием инфраструктуры Jersey/JAX-RS. Он уже поддерживает List s, но когда дело доходит до Map s, нет MessageBodyWriter. И даже если бы я вставлял Ma в класс-оболочку, в XML-схеме нет типа Map.

Любые практические советы о том, как маршалировать карту в документ XML/JSON в Джерси?

Ответы

Ответ 1

Я знаю, что очень поздно ответить, но я надеюсь, что когда-нибудь это поможет кому-нибудь:) Самое легкое и быстрое исправление, которое я применил, -

@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();
}

Вывод: {    "1": "abc",    "2": "def",    "3": "ghi" }

Это определенно поможет вам решить вашу проблему.

Ответ 2

Это очень легко сделать в Java EE 7.

Класс ресурсов 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);
    }
}

Как вы можете видеть, вы можете настроить разные классы как jsonProvider:

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

или

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

или

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

Ответ 3

Я знаю, что это уже давно, но, возможно, кто-то найдет это полезным.

У меня есть аналогичная проблема, и для меня это похоже, что только Джексон в настоящее время поддерживает такое прямое сопоставление Map to JSON.

В Джерси это так же просто, как вернуть карту из метода ресурсов:

@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;
  }
}

и доступ к нему от клиента:

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

С Jackson (в отличие от MOXy) вам необходимо зарегистрировать JacksonFeature вручную, например. в подклассе javax.ws.rs.core.Application (или ResourceConfig в Джерси):

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

И не забудьте использовать модуль Jack Jackson на пути к классам. В maven просто добавьте:

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

без maven, может быть немного сложнее добавить все зависимости. И все это должно сработать. По крайней мере, с провайдером Джексона.

Это не сработало для меня в Jettison, и id еще не работает в MOXy (там

Ответ 4

Решение, которое сработало для меня (Использование jettison):

@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();
}

Ответ 5

По умолчанию Джерси использует поставщика MOXy XML/JSON. Поэтому, если вы хотите использовать MOXy, вам нужно добавить отдельный адаптер. Простым решением является удаление зависимости MOXy от pom.xml и добавление зависимости Jackson. Джексон позаботится обо всем.

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

Извините, я не знаю, почему MOXy является поставщиком по умолчанию в 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();
}

Спасибо,