JacksonXmlRootElement с динамическим значением localName - PullRequest
1 голос
/ 14 октября 2019

Я обновляю POJO, который мы отображаем на XML, и единственное отличие состоит в том, что кто-то хочет и старый XML, и какой-то новый, и единственное отличие заключается в имени корневого упаковщика (все те же поля)), например, в настоящее время корневая метка Xml установлена ​​на ExistingName, и они хотят новое значение, например BrandNewName, со всеми одинаковыми полями. И все равно получить старое. Есть ли способ просто перевернуть это в POJO?

Я подумал, что мог бы сделать это с некоторым наследованием и базовым классом с двумя реализациями, но это казалось излишним

Я знаю, что могу установить корневой тег с помощью @JacksonXmlRootElement, но возможно лиустановите для него имя переменной.

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

Ответы [ 2 ]

1 голос
/ 17 октября 2019

Я обнаружил, что Получить Jackson XMLMapper, чтобы установить имя корневого элемента в коде и просто установить с помощью

XmlMapper mapper = new XmlMapper();
.writer()
.withRootName(myFieldName)
.writeValueAsString(myPojo ));
0 голосов
/ 17 октября 2019

Вы можете использовать функцию 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>
...