Вопрос по json – Как повторно использовать JSON / JAXB Джерси для сериализации?

28

У меня есть служба JAX-RS REST, реализованная с использованием Джерси. Одна из замечательных особенностей JAX-RS / Jersey заключается в том, как легко POJO можно превратить в службу REST, просто добавив несколько аннотаций Java ... в том числе простой механизм преобразования POJO в JSON - используя аннотации JAXB.

Теперь я хотел бы иметь возможность воспользоваться этой замечательной функцией JSON-ifying для целей, не относящихся к REST - я бы хотел иметь возможность просто сериализовать некоторые из этих объектов на диск в виде текста JSON. Вот пример объекта JAXB, который я хотел бы сериализовать:

@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 может превратить один из них в json без дополнительной информации. Мне интересно, раскрыл ли Джерси эту функциональность в API для нужд, подобных моей? Мне пока не повезло найти его ...

Благодарность

ОБНОВЛЕНИЕ 2009-07-09: Я узнал, что могу использовать объект Providers дляпочт делай то, что я хочу:

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

  uw.writeTo(....)

... Это записывает объект как json в любой выходной поток, что было бы идеально для меня, но я могу получить только объект Providers, используя @Context из объекта @Component. Кто-нибудь знает, как получить к нему доступ из обычного, без аннотации POJO? Благодарность

Я тоже могу назвать класс для начальной загрузки. Archimedes Trajano
Я тоже пытаюсь найти информацию по этому вопросу, но я искал что-то, что использует только API-интерфейсы javax. * / Java. * (Я не против добавления дополнительных библиотек для тестирования JUnit, но я ожидаю, что они будут присутствовать. в JEE6 RI Archimedes Trajano

Ваш Ответ

7   ответов
19

используете ли вы mapped (), badgerfish () или natural (). Естественным обычно является то, что люди хотят. И это реализовано с использованием очень хорошего (и очень быстрого) автономного процессора JSON Джексона, я полагаю, что происходит от Object-> JAXB-> JSON. Однако Джексон также предоставляет своего собственного провайдера JAX-RS для прямого выбора Object-> JSON.

На самом деле, они даже добавили поддержку аннотаций JAXB. Посмотри н

http: //wiki.fasterxml.com/JacksonJAXBAnnotation

Я думаю, это то, что ты ищешь. Джексон выполняет Object <-> JSON-обработку ... Джерси просто звонит вам

Jackson.codehaus.org для проекта Джексон домой Andy O
Спасибо, Энди. Это действительно звучит как то, что я ищу. Я просто не хочу добавлять ненужные дополнительные зависимости. Благодарность ctwomey
Хорошо, подумайте об этом так: вам нужна библиотека для сериализации XML (JAXB, XStream или тому подобное). Вам нужна библиотека JSON для JSON: JAXB не предоставляет ее; Джерси также отправляет его в библиотеку. Так что вопрос скорее в том, какие библиотеки добавить; Не нужно ли вам что-то добавить. Так что Джексон (или json-tools, gson) может сделать это легко. И провайдеры JAX-RS на самом деле немногим больше, чем диспетчеры, которые работают с типами носителей, выбирая, какое «представление» представить (json, xml, ...), а затем вызывая соответствующую библиотеку. StaxMan
6

ов с JSON (с использованием Jackson):

http: //ondra.zizka.cz/stranky/programovani/java/jaxb-json-jackson-howto.tex

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

ема в том, что JAXB не поддерживает пустые массивы. Поэтому при сериализации что-то вроде этого ...

List myArray = new ArrayList();

... для json с помощью jaxb-аннотаций все ваши пустые массивы становятся нулевыми вместо [].

Чтобы решить эту проблему, вы можете просто сериализовать свои pojos напрямую в json через Джексона.

Посмотрите на это из руководства пользователя Джерси:http: //jersey.java.net/nonav/documentation/latest/user-guide.html#d0e195

Это лучший способ использовать провайдера Джексона без JAXB. Более того, вы всегда можете использовать последнюю версию Джексона, загрузив jackson-all-x.y.z-jar с его веб-сайта.

Этот метод не помешает вашим аннотациям jaxb, поэтому я бы предложил попробовать!

1

а JAX-RS полностью сосредоточен на предоставлении стандартного способа реализации конечной точки для службы REST, а вопросы сериализации полезной нагрузки оставлены другим стандартам.

Я думаю, что если бы они включили сериализацию объектов в стандарт JAX-RS, он быстро превратился бы в крупного многоголового зверя, которого было бы трудно реализовать, и потерял бы часть своего внимания.

Я ценю то, как Джерси сфокусирован на предоставлении чистых и простых в использовании конечных точек REST. В моем случае я только что выделил родительский объект, в котором есть все компоненты JAXB, поэтому маршалинг объектов между двоичным и XML очень чистым.

Я не думаю, что мне было ясно. Дело в том, что Джерси уже переводит объекты JAXB в JSON. Я не ищу, чтобы Джерси добавил поддержку «сериализации», а скорее получил доступ к функциональности провайдера, которая уже есть для моегособственны код сериализации. Я обновлю свой вопрос, чтобы добавить ясности. Благодарность ctwomey
1

е для создания необходимых вам объектов JSON. Вам необходимо включить следующие зависимости (вы можете использовать пакет, но это вызовет проблемы, если вы используете Weld для тестирования):

    <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>

Оттуда вы можете создать аннотированный класс JAXB. Ниже приведен пример:

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

Затем вы можете создать следующий юнит-тест:

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

Преимущество этого подхода заключается в том, что он поддерживает все в JEE6 API, внешние библиотеки явно не нужны, кроме как для тестирования и получения поставщиков. Однако вам необходимо создать реализацию MultivaluedMap, поскольку в стандарте ничего не предусмотрено, и мы фактически не используем ее. Этоможе также будет медленнее, чем GSON, и намного сложнее, чем необходимо.

0

но было бы предвидеть, что потребуется поддержка JSON для POJO как стандартного оборудования. Необходимость исправления идентификаторов JSON специальными символами не имеет смысла, если ваша реализация - JSON, а ваш клиент - JavaScript RIA.

Кроме того, Java Beans НЕ являются POJO. Я хотел бы использовать что-то подобное на внешней поверхности моего веб-уровня:

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

Нет конструктора по умолчанию, нет шума геттера / сеттера, просто POJO с моими собственными аннотациями.

Я не думаю, что это ошибка JAXB: JAXB - это API для XML, а не для других форматов. Но тогда возникает вопрос, следует ли использовать JAXB API для работы с другими форматами - если да, то нужны обходные пути. XML! = JSON. Кстати: Джексон, который уже упоминался, позволяет использовать не Bean POJO; можно использовать поля или методы получения / установки, использовать реальные реальные конструкторы и так далее. Он может использовать аннотации JAXB в качестве дополнительной необязательной информации, если пользователь действительно этого хочет. Но это им не нужно. StaxMan

Похожие вопросы