@XmlElementWrapper Сериализация не работает с использованием аннотаций Jackson JaxB - PullRequest
0 голосов
/ 03 июня 2018

Мы используем аннотации Jackson 2.9.4 и JaxB для сериализации в JSON.

Аннотация @XMLElementWrapper не добавляет дополнительный уровень переноса, как ожидалось.Вместо этого он просто меняет имя элемента.

    @XmlRootElement(name = "revision")
    class A {
        private List<Integer> tickets = Arrays.asList(3,4,5);

        @XmlElement(name = "ticket")
        @XmlElementWrapper(name = "tickets")
        public List<Integer> getTickets() { return tickets; }
    }

        public void test() throws Exception {
            ObjectMapper mapper = new ObjectMapper();
            JaxbAnnotationModule jaxbAnnotationModule = new JaxbAnnotationModule();
            mapper.registerModule(jaxbAnnotationModule);
            A a = new A();
            System.out.println(mapper.writeValueAsString(a));

        }

Ожидаемый результат:

{"tickets": {"ticket": [3,4,5]}}

но фактический результат равен

{"tickets": [3,4,5]}

1 Ответ

0 голосов
/ 03 июня 2018

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

Сериализатору необходимо имя нового обернутого слоя.

Пользователь может указать имя с помощью пользовательской аннотации.

Джексон создает экземпляры пользовательских сериализаторов в фабрике сериализаторов, поэтому мне нужно переопределить функцию, которая создает сериализатор, прочитать аннотацию и сообщить экземпляру сериализатораимя, указанное там.

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

public class XMLWrapperCollectionSerializer extends JsonSerializer<Collection> {
    private String innerFieldName = null;
    public void setInnerFieldName(String value) { this.innerFieldName = value; }
    public String getInnerFieldName() { return innerFieldName; }
    @Override
     public void serialize(Collection myClass, JsonGenerator generator, SerializerProvider provider) 
        throws JsonGenerationException, IOException {
        generator.writeStartObject();
        generator.writeFieldName(innerFieldName);
        provider.defaultSerializeValue(myClass, generator);
        generator.writeEndObject();
    } 
}

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public  @interface XMLWrapperSerializerAttributes{
  String innerFieldName();
}

public class CustomSerializerFactory extends BeanSerializerFactory {

    public CustomSerializerFactory() {
        super(null);
    }

    @Override
    protected JsonSerializer<Object> findSerializerFromAnnotation(SerializerProvider prov, Annotated a) throws JsonMappingException
    {
        JsonSerializer<Object> serializer = super.findSerializerFromAnnotation(prov,  a);

        Object serializerAsObject = (Object)serializer;
        if (serializerAsObject instanceof XMLWrapperCollectionSerializer )
        {
            XMLWrapperCollectionSerializer wrapperSerializer = (XMLWrapperCollectionSerializer) serializerAsObject;
            if ( ((XMLWrapperCollectionSerializer) serializerAsObject).getInnerFieldName() == null )
            {
             XMLWrapperSerializerAttributes annotation = a.getAnnotation(XMLWrapperSerializerAttributes.class);
             if ( annotation == null )
                throw new RuntimeException("XMLWrapperListSerializer must have innerFieldName, by annotation or code");
             wrapperSerializer.setInnerFieldName(annotation.innerFieldName());
            }
        }
        return serializer;
    }


}
@XmlRootElement(name = "revision")
class A {
    private List<Integer> tickets = new ArrayList(Arrays.asList(3,4,5));

    @XMLWrapperSerializerAttributes(innerFieldName="ticket")
    @JsonSerialize(using=XMLWrapperCollectionSerializer.class)
    @XmlElementWrapper(name = "tickets")
    @XmlElement(name = "ticket")
    public List<Integer> getTickets() { return tickets; }

public class XMLElementWrapperTest{

    @Test
    public void test() throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializerFactory(new CustomSerializerFactory());
        JaxbAnnotationModule jaxbAnnotationModule = new JaxbAnnotationModule();
        mapper.registerModule(jaxbAnnotationModule);
        A a = new A();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...