简体   繁体   English

@XmlElementWrapper序列化无法使用Jackson JaxB注释进行工作

[英]@XmlElementWrapper Serialization not working using Jackson JaxB Annotations

We are using Jackson 2.9.4 and JaxB Annotations to serialize to JSON. 我们正在使用Jackson 2.9.4和JaxB Annotations序列化为JSON。

The @XMLElementWrapper annotation is not adding an extra wrapping level as expected. @XMLElementWrapper注释未按预期添加额外的包装级别。 Instead, it is just changing the name of the element. 相反,它只是更改元素的名称。

    @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));

        }

Expected output is 预期输出为

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

but Actual output is 但实际输出是

{"tickets":[3,4,5]} {“票”:[3,4,5]}

I am considering working around this using a custom Jackson serializer and a custom annotation which will specify the name of the wrapper layer. 我正在考虑使用自定义Jackson序列化程序和自定义批注来解决此问题,该批注将指定包装层的名称。

The serializer needs the name of the new wrapped layer. 序列化器需要新包装层的名称。

The user can specify the name using a custom annotation. 用户可以使用自定义注释指定名称。

Jackson creates instances of Custom Serializers in a Serializer Factory so I need to override the function which creates the Serializer, read the annotation, and let the serializer instance know the name specified there. 杰克逊在序列化器工厂中创建了自定义序列化器的实例,因此我需要重写创建序列化器的功能,读取注释,并让序列化器实例知道在此指定的名称。

I am a bit concerned about fragility here as overriding serialization factory is not well documented at all, and I'm not sure what side effects it may cause. 我有点担心这里的脆弱性,因为根本没有很好地记录重写的序列化工厂,而且我不确定它可能引起什么副作用。

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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM