Настройте Джерси / Джексон, чтобы НЕ использовать аннотацию поля @XmlElement для именования полей JSON - PullRequest
14 голосов
/ 15 февраля 2011

Я управляю службой REST в Джерси.POJO, которые представляют мои ресурсы, представляют собой простые Java-классы, аннотированные JAXB (XML) (они генерируются из определения схемы - поэтому они имеют аннотации).

Я хочу, чтобы Джерси / Джексон игнорировал XML-аннотации.Я сделал эту конфигурацию в своем файле web.xml (как уже упоминалось здесь ):

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

Теперь я ожидал, что аннотация @XMLElement больше не будет использоваться для политики именования полей JSON.

Но, глядя на это поле Java (член)

@XmlElement(name = "person", required = true)
protected List<Person> persons;

Я все еще получаю следующее представление JSON:

....,"person":[{"name":"FooBar", ....... (person without the 's')

Все остальные поля также все еще получают свои имена JSON изаннотация @XmlElement вместо имени поля Java.

Я хотел бы получить вывод JSON, как описано в примере Джексона Полная привязка данных (POJO) .

Он отлично работает в таких простых тестах, как этот (с моими аннотированными классами XML):

  ObjectMapper mapper = new ObjectMapper(); 
  mapper.writeValue(System.out, myObject);

, но встроен в Джерси. Я не получил ожидаемого вывода JSON.

Есть ли другие варианты их конфигурации вДжерси, чтобы получить «простое» представление POJO JSON (потому что это лучше всего подходит для клиентов, которые должны десериализовать результат JSON).

Спасибо, Клаус

Подробное решение

(1) Реализуйте ContextResolver для Jacksons ObjectMapper, который создает ObjectMapper, который не будет использовать аннотации.

package foo.bar.jackson;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;

/**
 * Customized {@code ContextResolver} implementation that does not use any
 * annotations to produce/resolve JSON field names.
 */
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonContextResolver implements ContextResolver<ObjectMapper> {

    private ObjectMapper objectMapper;

    /**
     * Creates a new instance.
     * 
     * @throws Exception
     */
    public JacksonContextResolver() throws Exception {
        this.objectMapper = new ObjectMapper().configure(
                DeserializationConfig.Feature.USE_ANNOTATIONS, false)
                .configure(SerializationConfig.Feature.USE_ANNOTATIONS, false);
        ;
    }

    /**
     * @see javax.ws.rs.ext.ContextResolver#getContext(java.lang.Class)
     */
    public ObjectMapper getContext(Class<?> objectType) {
        return objectMapper;
    }
}

(2) Зарегистрируйте bean-компонент ContextResolver Spring в своем приложении. Xml

<bean class="foo.bar.jackson.JacksonContextResolver"/>

1 Ответ

6 голосов
/ 15 февраля 2011

На низком уровне, что необходимо для того, чтобы ObjectMapper НЕ использовал JAXBAnnotationIntrospector, а только по умолчанию JacksonAnnotationIntrospector.Я думаю, вы должны иметь возможность просто создать ObjectMapper (который по умолчанию не добавляет интроспектор JAXB) и зарегистрировать его через стандартный механизм провайдера JAX-RS.Это должно переопределить ObjectMapper, который иначе мог бы создать функциональность POJO mapper.

...