2009-07-01 3 views
28

У меня есть сервис JAX-RS REST, выполненный с использованием Джерси. Одной из замечательных особенностей JAX-RS/Jersey является то, как легко POJO можно превратить в службу REST, просто воспользовавшись несколькими аннотациями Java ... включая тривиально простой механизм перевода POJO в JSON - с помощью аннотаций JAXB.Как использовать 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; 
} 

Джерси может превратить один из них в формате JSON без дополнительной информации. Мне интересно, предоставил ли Джерси эту функциональность в API для таких потребностей, как мой? Мне не повезло найти его до сих пор ...

Спасибо!

UPDATE 2009-07-09: Я узнал, что я могу использовать провайдеры возражают почти делать именно то, что я хочу:

@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? Благодаря!

+0

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

+0

Я тоже в порядке с вызовом класса для начальной загрузки. –

ответ

19

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

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

http://wiki.fasterxml.com/JacksonJAXBAnnotations

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

+1

http://jackson.codehaus.org/ для jackson project home –

+0

Спасибо, Энди. Это действительно похоже на то, что я ищу. Я просто не хочу добавлять лишние дополнительные зависимости. Благодаря! – ctwomey

+2

Ну, подумайте об этом так: вам нужна библиотека для сериализации XML (JAXB, XStream или такая). Вам нужна библиотека JSON для JSON: JAXB не предоставляет ее; Джерси также отправляет его в библиотеку. Поэтому вопрос скорее заключается в том, какой lib (s) добавить; не нужно ли что-то добавлять. Так что Джексон (или json-tools, gson) может сделать это легко. И провайдеры JAX-RS на самом деле немного больше, чем диспетчеры, которые работают с типами носителей, выбирая, какой «просмотр» для представления (json, xml, ...), а затем вызывает соответствующую библиотеку. – StaxMan

1

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

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

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

+0

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

0

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

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

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

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

+0

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

3

JAXB аннотации отлично работают при преобразовании в XML. Основная проблема заключается в том, что JAXB не поддерживает пустые массивы. Так что, когда сериализации что-то вроде этого ...

List myArray = new ArrayList(); 

... в JSon через JAXB anottations все ваши пустые массивы утратившим вместо [].

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

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

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

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

5
ObjectMapper mapper = new ObjectMapper(); 
String str = mapper.writeValueAsString(pojoObject); 
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\"")); 

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

 Смежные вопросы

  • Нет связанных вопросов^_^