2014-11-12 3 views
1

Я начал с службы, которая потребляет и производит выходные данные в JSON. Я использую resteasy-jackson-provider для (de) marshalling, который берет информацию из описания класса. Через некоторое время меня попросили добавить XML как MediaType. Поэтому я аннотировал мои DTO с аннотациями JAXB и добавил resteasy-jaxb-provider. В результате я заметил, что произведенный вывод JSON происходит из аннотаций JAXB, которые отличаются от исходного формата.RestEasy, как предотвратить сортировку JAXB аннотированных POJO и от JSON

Я нахожусь в RestEasy Version 3.0.4. Как описано я использую следующие провайдер

  1. Resteasy-ДЖЕКСОН-провайдер
  2. Resteasy-AXB-провайдер.
  3. resteasy-jettison-provider, потому что я интегрировал RestEasy в Spring, и этот провайдер является транзитивной зависимостью.

я в курсе проблемы, когда я

  1. используется XmlElementWrapper для списков и когда
  2. я написал обычай XmlAdapter который сериализующий сложную структуру Map<String, List<String>> данных. Запросы с XML MediaType прекрасны. Запросы с JSON MediaType вызывают исключение. Джексон, похоже, использует XmlAdapter для получения дополнительной информации. Раньше это было не так. Джексону удалось собрать Маршу без аннотаций JAXB.

    org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Нераспознанное поле "клиент" (класс x.y.z.OptionalParametersMapType), не помеченный как игнорируемые в [Источник: [email protected]; строка: 1, столбец: 131] (через цепочку ссылок: xyzRequest ["optional"] -> xyzOptionalParametersMapType ["customer"]) at org.codehaus.jackson.map.exc.UnrecognizedPropertyException.from (UnrecognizedPropertyException.java : 53) на org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException (StdDeserializationContext.java:267) на org.codehaus.jackson.map.deser.std.StdDeserializer.reportUnknownProperty (StdDeserializer.java:673) at org.codehaus.jackson.map.deser.std.StdDeserializer.handleUnknownProperty (StdDeserializer.java:659) at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty (BeanDeserializer.java:1365) at org.codehaus .jackson.map.deser.BeanDeserializer._handleUnknown (BeanDeserializer.java:725) at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject (BeanDeserializer.java:703) at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize (BeanDeserializer.java:580) at org.codehaus. jackson.xc.XmlAdapterJsonDeserializer.deserialize (XmlAdapterJsonDeserializer.java:59) at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize (SettableBeanProperty.java:299) at org.codehaus.jackson.map.deser.SettableBeanProperty $ FieldProperty.deserializeAndSet (SettableBeanProperty.java:579) на org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject (BeanDeserializer.java:697) в org.codehaus.jackson.map.deser.BeanDeserializer.deserialize (BeanDeserializer. java: 580) at org.codehaus.jackson.map.ObjectMapper._readValue (ObjectMapper.java:2704) at org.codehaus.jackson.map.ObjectMapper.readValue (ObjectMapper.java:1315) в org.codehaus.jackson.jaxrs.JacksonJsonProvider.readFrom (JacksonJsonProvider.java:419)

Итак, как я могу предотвратить Resteasy от использования аннотаций JAXB для сортировки и от JSON?

Вот класс запроса:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "domainRecommendationRequest") 
public class Request { 

    @XmlJavaTypeAdapter(OptionalParametersXmlAdapter.class) 
    private Map<String, List<String>> optional = new HashMap<>(); 

} 

Вот это XMLAdapter:

@Override 
public class OptionalParametersXmlAdapter extends XmlAdapter<OptionalParametersMapType, Map<String, List<String>>> { 

    public OptionalParametersMapType marshal(Map<String, List<String>> v) throws Exception { 
     OptionalParametersMapType result = new OptionalParametersMapType(); 
     List<OptionalParameterItemType> optionalParameterItemTypes = new ArrayList<>(); 

     Set<String> keySet = v.keySet(); 

     for (String parameterName : keySet) { 
      OptionalParameterItemType item = new OptionalParameterItemType(); 
      item.name = parameterName; 
      item.values = v.get(parameterName); 
      optionalParameterItemTypes.add(item); 
     } 

     result.parameter = optionalParameterItemTypes; 

     return result; 
    } 
} 

Вот обертка для карты:

public class OptionalParametersMapType { 
    public List<OptionalParameterItemType> parameter = new ArrayList<>(); 

} 

Вот фактическая запись на карте статья:

public class OptionalParameterItemType { 

    @XmlAttribute 
    public String name; 

    @XmlElementWrapper(name = "values") 
    @XmlElement(name = "value") 
    public List<String> values = new ArrayList<>(); 
} 

Это то, что я ожидаю в запросе JSON:

{"optional":{"customer":["Mike"]}} 

Как вы можете видеть, я намерен иметь различный формат в XML.

ответ

0

Проблема resteasy-jackson-provider зависит от jackson-module-jaxb-annotations, которая используется для отображения аннотаций JAXB/аннотированных классов для JSON. Теперь в нормальном явном использовании ObjectMapper для того, чтобы использовать этот модуль, мы должны были бы явно зарегистрировать этот модуль, как (см here)

ObjectMapper objectMapper = new ObjectMapper(); 
JaxbAnnotationModule module = new JaxbAnnotationModule(); 
objectMapper.registerModule(module); 

-- OR -- 

AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(); 
objectMapper.setAnnotationIntrospector(introspector); 

Это, как говорится, это появляется (не подтверждено любые факты, но выглядит вероятным), что когда ObjectMapper создается для вашей сериализации, когда заметки JAXB замечены, модуль автоматически регистрируется.

Я не знаю, каких-либо возможных аннотаций, мы можем использовать, чтобы остановить это, но один из способов решения этой проблемы является создание ContextResolver для ObjectMapper, где мы не зарегистрировать модуль JAXB.

@Provider 
public class ObjectMapperContextResolver 
        implements ContextResolver<ObjectMapper> { 
    @Override 
    public ObjectMapper getContext(Class<?> type) { 
     return new ObjectMapper(); 
    } 
} 

После того, как мы фиксируем, что с нашим приложением JAX-RS, будет контекст распознаватель используется для получения ObjectMapper. Мы могли бы сконфигурировать ObjectMapper дальше, но это всего лишь пример. Протестируйте его, и он работает так, как ожидалось.

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