#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 для объектно-реляционного отображения.