具有动态 localName 值的 JacksonXmlRootElement

JacksonXmlRootElement with dynamic localName value

我正在更新我们映射到 XMLPOJO,唯一的区别是有人想要旧的 XML 和一些新的,唯一的区别是根包装器名称(所有相同的字段),例如目前,根 Xml 标签设置为 ExistingName,他们想要一个新值,如 BrandNewName,具有所有相同的字段。而且还是老样子。有没有办法在 POJO 中翻转这个?

我想我可以通过一些继承和一个带有两个实现的基础 class 来做到这一点,但似乎有点过分了

我知道我可以用 @JacksonXmlRootElement 设置根标签,但是否可以将其设置为变量名。

@JacksonXmlRootElement(localName = 'ExistingName')
class MyPojo {
    String commonVar1
    String commonVar1
    String commonVar1
}

您可以使用 MixIn 功能并动态声明根类型的名称:

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

public class XmlMapperApp {

    public static void main(String[] args) throws Exception {
        XmlMapper xmlMapperOld = new XmlMapper();
        xmlMapperOld.addMixIn(MyPojo.class, MyPojoExistingNameMinIn.class);

        XmlMapper xmlMapperNew = new XmlMapper();
        xmlMapperNew.addMixIn(MyPojo.class, MyPojoBranNewNameMinIn.class);

        System.out.println(xmlMapperOld.writeValueAsString(new MyPojo()));
        System.out.println(xmlMapperNew.writeValueAsString(new MyPojo()));
    }
}

@JacksonXmlRootElement(localName = "ExistingName")
interface MyPojoExistingNameMinIn {
}

@JacksonXmlRootElement(localName = "BrandNewName")
interface MyPojoBranNewNameMinIn {
}

以上代码打印:

<ExistingName><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName>
<BrandNewName><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></BrandNewName>

但是我们也可以创建一个额外的POJO来存储我们想要在序列化过程中分配的对象和名称。为了让它工作,我们需要实现自定义 JsonSerializer 并实现该行为。示例解决方案如下所示:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.util.NameTransformer;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializer;

import javax.xml.namespace.QName;
import java.io.IOException;
import java.util.Objects;

public class XmlMapperApp {

    public static void main(String[] args) throws Exception {
        XmlMapper xmlMapper = new XmlMapper();
        for (char c = 65; c < 70; c++) {
            System.out.println(xmlMapper.writeValueAsString(new PersistAs("ExistingName_" + c, new MyPojo())));
        }
    }
}

class PersistAsJsonSerializer extends JsonSerializer<PersistAs> {

    @Override
    public void serialize(PersistAs value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        ToXmlGenerator xmlGen = (ToXmlGenerator) gen;
        // set desired name
        xmlGen.setNextName(new QName(value.getName()));
        xmlGen.writeStartObject();

        // serialise fields
        XmlBeanSerializer serializer = (XmlBeanSerializer) serializers.findValueSerializer(value.getValue().getClass());
        JsonSerializer<Object> unwrappingSerializer = serializer.unwrappingSerializer(NameTransformer.NOP);
        unwrappingSerializer.serialize(value.getValue(), gen, serializers);

        // end of root
        gen.writeEndObject();
    }
}

@JsonSerialize(using = PersistAsJsonSerializer.class)
class PersistAs {
    private final String name;
    private final Object value;

    public PersistAs(String name, Object value) {
        this.name = Objects.requireNonNull(name);
        this.value = Objects.requireNonNull(value);
    }

    public String getName() {
        return name;
    }

    public Object getValue() {
        return value;
    }

    @Override
    public String toString() {
        return "PersistAs{" +
                "name='" + name + '\'' +
                ", value=" + value +
                '}';
    }
}

以上代码打印:

<ExistingName_A><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName_A>
<ExistingName_B><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName_B>
<ExistingName_C><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName_C>
<ExistingName_D><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName_D>
<ExistingName_E><commonVar1>Var1</commonVar1><commonVar2>Var2</commonVar2><commonVar3>Var3</commonVar3></ExistingName_E>

我最终找到 Get Jackson XMLMapper to set root element name in code 并使用

进行设置
XmlMapper mapper = new XmlMapper();
.writer()
.withRootName(myFieldName)
.writeValueAsString(myPojo ));