gpt4 book ai didi

java - @XmlElementWrapper 序列化无法使用 Jackson JaxB 注释工作

转载 作者:行者123 更新时间:2023-11-30 10:15:01 25 4
gpt4 key购买 nike

我们使用 Jackson 2.9.4 和 JaxB Annotations 序列化为 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]}

最佳答案

我正在考虑使用自定义 Jackson 序列化程序和自定义注释来解决此问题,该注释将指定包装层的名称。

序列化器需要新包装层的名称。

用户可以使用自定义注释指定名称。

Jackson 在序列化器工厂中创建自定义序列化器的实例,因此我需要重写创建序列化器的函数,读取注释,并让序列化器实例知道那里指定的名称。

我有点担心这里的脆弱性,因为压倒一切的序列化工厂根本没有很好的记录,而且我不确定它可能会导致什么副作用。

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

关于java - @XmlElementWrapper 序列化无法使用 Jackson JaxB 注释工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50665609/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com