Java.util.Сопоставление с объектом JSON с помощью Jersey / JAXB / Jackson

#java #json #rest #jersey #jackson

#java #json #остальное #джерси #джексон

Вопрос:

Я пытался создать веб-сервис Jersey REST. Я хочу получать и испускать объекты JSON из классов Java, подобных следующим:

 @XmlRootElement
public class Book {

    public String code;

    public HashMap<String, String> names;

}
  

Это должно быть преобразовано в JSON следующим образом:

 {
    "code": "ABC123",
    "names": {
        "de": "Die fabelhafte Welt der Amelie",
        "fr": "Le fabuleux destin d'Amelie Poulain"
    }
}
  

Однако я не могу найти стандартное решение для этого. Кажется, что каждый реализует свое собственное решение оболочке. Это требование кажется мне чрезвычайно простым; я не могу поверить, что это общепринятое решение для этого, тем более что Jersey действительно одна из самых интересных частей Java.

Я также пробовал обновление до Jackson 1.8, которое дает мне только это, что является чрезвычайно запутанным JSON:

 {
    "code": "ABC123",
    "names": {
        "entry": [{
            "key": "de",
            "value": "Die fabelhafte Welt der Amelie"
        },
        {
            "key": "fr",
            "value": "Le fabuleux destin d'Amelie Poulain"
        }]
    }
}
  

Существуют ли какие-либо предлагаемые решения для этого?

Ответ №1:

Я не знаю, почему это не настройка по умолчанию, и мне потребовалось некоторое время, чтобы понять это, но если вы хотите, чтобы преобразование JSON с помощью Jersey работало, добавьте

     <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
  

для вашего web.xml и все ваши проблемы должны быть решены.

PS: вам также нужно избавиться от @XmlRootElement аннотаций, чтобы заставить его работать

Комментарии:

1. 1 за подсказку. Но имейте в виду, что сопоставление POJO также вернет нулевые значения в JSON. Я предпочитаю JAXB и работаю со списками, которые включают дополнительные POJO.

2. Это настройка на стороне сервера. Чтобы сделать это на клиенте: ClientConfig ClientConfig = new DefaultClientConfig(); ClientConfig.getFeatures().put(JSONConfiguration. FEATURE_POJO_MAPPING, логическое значение. ВЕРНО); Client client = Client.create(ClientConfig);

3. @Jan Что, если мне нужно преобразовать книгу в json и в xml (запрос с принятием )? Если я удалю XmlRootElement, сериализация xml больше не будет работать

4. Вау. Это был бы отличный ответ, за исключением того, что добавление, как было предложено в web.xml независимо от того, удалены ли @XmlRootElement и связанные аннотации, в результате получается: com.sun.jersey.spi.container. СЕРЬЕЗНЫЙ сбой при запросе контейнера: программа чтения тела сообщения для Java-класса com.hp.web.user.dto.ProfileDto и Java-класса com.hp.web.user.dto.ProfileDto и MIME-носителя типа application / json; кодировка = UTF-8 не найдена.

5. Да, то, что сказал Расс. Это не решение выдает ошибку «автор тела сообщения не найден»

Ответ №2:

Вы можете использовать google-gson. Вот пример кода:

     @Test
    public void testGson(){
       Book book = new Book();
       book.code = "1234";
       book.names = new HashMap<String,String>();
       book.names.put("Manish", "Pandit");
       book.names.put("Some","Name");
       String json = new Gson().toJson(book);
       System.out.println(json);
   }
  

Результат таков {"code":"1234","names":{"Some":"Name","Manish":"Pandit"}}

Комментарии:

1. Спасибо, но меня особенно интересовало решение, интегрированное с Jersey.

2. Я предпочитаю этот подход для возврата сложной структуры данных, отличной от простого POJO. Он отлично работает, он интегрируется с Jersey (вам нужно только вернуть «строку» в вашем методе get), и вам не нужно путаться с web.xml конвертеров.

Ответ №3:

Я знаю, что об этом спрашивали давным-давно, но со временем все изменилось, поэтому для последней версии Jersey v2.22, в которой больше нет пакета com.sun.jersey, эти две зависимости добавлены в проект pom.xml решена та же проблема:

 <dependency>
  <groupId>org.glassfish.jersey.media</groupId>
  <artifactId>jersey-media-json-jackson</artifactId>
  <version>2.22</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.jaxrs</groupId>
  <artifactId>jackson-jaxrs-json-provider</artifactId>
  <version>2.5.4</version> <!-- jackson version used by jersey v2.22 -->
</dependency>
  

Не нужно ничего добавлять в web.xml .
Первая зависимость проинструктирует джерси использовать jackson для преобразований POJO в JSON.
Вторая зависимость зарегистрирует jackson как JSON-провайдера Джерси.

Также для решения проблемы с нулевым значением в POJO добавьте эту аннотацию в класс POJO:

 @JsonInclude(JsonInclude.Include.NON_NULL)
  

Ответ №4:

 @POST
@Consumes("application/json")
public void createBook(Book book)
{
 .....
 .....
}
  

Конечно, вам нужно иметь getter / setter для каждого свойства в Book.

Также рекомендуется использовать класс-оболочку (который обычно является map), чтобы избежать создания нескольких DTO для каждого вида данных, которые вы хотите отправить. Проще просто сериализовать / десериализовать с помощью map и как часть бизнес-логики преобразовать его в соответствующий POJO для внутренней обработки, особенно если вы используете этот POJO для объектно-реляционного отображения.