【问题标题】:JacksonXmlRootElement with dynamic localName value具有动态 localName 值的 JacksonXmlRootElement
【发布时间】:2020-02-11 09:32:57
【问题描述】:

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

我想我可以通过一些继承和一个具有两个实现的基类来做到这一点,但似乎有点矫枉过正

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

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

【问题讨论】:

  • 反序列化期间XML 中的根元素名称应该不是问题。 <ExistingName>...</ExistingName> - 将被反序列化,<MyPojo>...</MyPojo> 将被正确反序列化。您对旧的 XML 文件有什么问题?
  • 旧的xml没有问题。它是有效的,他们仍然想要它。他们只是在其他情况下也想要相同的 xml,但具有不同的根名称。那么,您是说 1)反序列化为 2)替换 ExistingName w/ BrandNewName
  • 那么,您想将相同的POJO 序列化为两个不同的根元素,对吗?您是使用一个全局 ObjectMapper 配置还是使用多个本地实例?
  • ``` XmlMapper xmlMapper = new XmlMapper() String xml = xmlMapper.writeValueAsString(save) ``` 注意,我可以通过创建一个包含所有字段的父类并扩展到两个子类,它们只是有不同的@JacksonXmlRootElement

标签: java xml jackson pojo xmlmapper


【解决方案1】:

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

XmlMapper mapper = new XmlMapper();
.writer()
.withRootName(myFieldName)
.writeValueAsString(myPojo ));

【讨论】:

    【解决方案2】:

    您可以使用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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-16
      • 2018-08-06
      • 1970-01-01
      • 1970-01-01
      • 2014-02-18
      相关资源
      最近更新 更多