Преобразование JSON в XML XmlMapper-Jackson 2.10

У меня есть pojos с @JsonProperties. Я использую их для чтения JSON и анализа в POJO. Теперь мне нужно опубликовать эти pojos в формате XML.

Требуемый формат XML для успешной публикации выглядит следующим образом (обратите внимание на тип пространства имен, форматирование типа xsi):

<network_objects>
    <network_object xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="subnetNetworkObjectDTO">
        <name>TestSubnet</name>
        <display_name>TestSubnet</display_name>
        <global>false</global>
        <application_id>3</application_id>
        <type>subnet</type>
        <ip>5.207.206.0</ip>
        <netmask>255.255.254.0</netmask>
    </network_object>
    <network_object xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="networkObjectGroupDTO">
        <name>Test01Subnets</name>
        <display_name>Test01Subnets</display_name>
        <application_id>3</application_id>
        <type>group</type>
    </network_object>
</network_objects>

Я передаю созданный класс приложения (показан ниже) для преобразования в XML

    ObjectMapper mapper = new XmlMapper(); 
    mapper.enable(SerializationFeature.INDENT_OUTPUT);        
    byte[] val = mapper.writeValueAsBytes(myApp);

Вывод немного отличается и не содержит xmlns, а xsi выглядит иначе. Он также имеет «Приложение» как root:

<Application>
 <network_objects>
  <network_object>
   <network_object>
    <@xsi.type>networkObjectGroupDTO</@xsi.type>
    <name>name</name>
    <display_name>displayName</display_name>
    <application_id>3</application_id>
    <type>group</type>
   </network_object>
  </network_object>
 </network_objects>
</Application>

Когда я вывожу класс в JSON, он выглядит так, как ожидалось (без «приложения» как root).

    ObjectMapper mapper = new ObjectMapper();
    mapper.enable(SerializationFeature.INDENT_OUTPUT);        
    byte[] val = mapper.writeValueAsBytes(myApp);


{
"network_objects" : {
"network_object" : [ {
  "@xsi.type" : "networkObjectGroupDTO",
  "name" : "name",
  "display_name" : "displayName",
  "application_id" : 3,
  "type" : "group"
   }
  }
}

Что мне нужно изменить с помощью XmlMapper() или POJO, чтобы правильно отформатировать XML?

Ниже приведены POJO, используемые для этого.

Класс приложения:

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"network_objects"
})
public class Application {

@JsonProperty("network_objects")
private NetworkObjects networkObjects;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();

@JsonProperty("network_objects")
public NetworkObjects getNetworkObjects() {
    return networkObjects;
}

@JsonProperty("network_objects")
public void setNetworkObjects(NetworkObjects networkObjects) {
    this.networkObjects = networkObjects;
}

@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
    return this.additionalProperties;
}

@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
    this.additionalProperties.put(name, value);
}

}

Класс NetworkObjects:

@JsonInclude(JsonInclude.Include.NON_NULL)
 @JsonPropertyOrder({
"network_object"
 })
 public class NetworkObjects {

@JsonProperty("network_object")
private List<NetworkObject> networkObject = null;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();

@JsonProperty("network_object")
public List<NetworkObject> getNetworkObject() {
    return networkObject;
}

@JsonProperty("network_object")
public void setNetworkObject(List<NetworkObject> networkObject) {
    this.networkObject = networkObject;
}

@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
    return this.additionalProperties;
}

@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
    this.additionalProperties.put(name, value);
}

 }

Класс сетевого объекта:

@JsonInclude(JsonInclude.Include.NON_NULL)
 @JsonPropertyOrder({
"@xsi.type",
"id",
"uid",
"name",
"display_name",
"global",
"comment",
"application_id",
"type",
"ip",
"access_allowed",
"member",
"last_ip",
"first_ip",
"netmask"
 })
 public class NetworkObject {

@JsonProperty("@xsi.type")
private String xsiType;
@JsonProperty("id")
private Integer id;
@JsonProperty("uid")
private String uid;
@JsonProperty("name")
private String name;
@JsonProperty("display_name")
private String displayName;
@JsonProperty("global")
private Boolean global;
@JsonProperty("comment")
private String comment;
@JsonProperty("application_id")
private Integer applicationId;
@JsonProperty("type")
private String type;
@JsonProperty("ip")
private String ip;
@JsonProperty("access_allowed")
private Boolean accessAllowed;
@JsonProperty("member")
private List<Member> member = null;
@JsonProperty("last_ip")
private String lastIp;
@JsonProperty("first_ip")
private String firstIp;
@JsonProperty("netmask")
private String netmask;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();

@JsonProperty("@xsi.type")
public String getXsiType() {
    return xsiType;
}

@JsonProperty("@xsi.type")
public void setXsiType(String xsiType) {
    this.xsiType = xsiType;
}

@JsonProperty("id")
public Integer getId() {
    return id;
}

@JsonProperty("id")
public void setId(Integer id) {
    this.id = id;
}

@JsonProperty("uid")
public String getUid() {
    return uid;
}

@JsonProperty("uid")
public void setUid(String uid) {
    this.uid = uid;
}

@JsonProperty("name")
public String getName() {
    return name;
}

@JsonProperty("name")
public void setName(String name) {
    this.name = name;
}

@JsonProperty("display_name")
public String getDisplayName() {
    return displayName;
}

@JsonProperty("display_name")
public void setDisplayName(String displayName) {
    this.displayName = displayName;
}

@JsonProperty("global")
public Boolean getGlobal() {
    return global;
}

@JsonProperty("global")
public void setGlobal(Boolean global) {
    this.global = global;
}

@JsonProperty("comment")
public String getComment() {
    return comment;
}

@JsonProperty("comment")
public void setComment(String comment) {
    this.comment = comment;
}

@JsonProperty("application_id")
public Integer getApplicationId() {
    return applicationId;
}

@JsonProperty("application_id")
public void setApplicationId(Integer applicationId) {
    this.applicationId = applicationId;
}

@JsonProperty("type")
public String getType() {
    return type;
}

@JsonProperty("type")
public void setType(String type) {
    this.type = type;
}

@JsonProperty("ip")
public String getIp() {
    return ip;
}

@JsonProperty("ip")
public void setIp(String ip) {
    this.ip = ip;
}

@JsonProperty("access_allowed")
public Boolean getAccessAllowed() {
    return accessAllowed;
}

@JsonProperty("access_allowed")
public void setAccessAllowed(Boolean accessAllowed) {
    this.accessAllowed = accessAllowed;
}

@JsonProperty("member")
public List<Member> getMember() {
    return member;
}

@JsonProperty("member")
public void setMember(List<Member> member) {
    this.member = member;
}

@JsonProperty("last_ip")
public String getLastIp() {
    return lastIp;
}

@JsonProperty("last_ip")
public void setLastIp(String lastIp) {
    this.lastIp = lastIp;
}

@JsonProperty("first_ip")
public String getFirstIp() {
    return firstIp;
}

@JsonProperty("first_ip")
public void setFirstIp(String firstIp) {
    this.firstIp = firstIp;
}

@JsonProperty("netmask")
public String getNetmask() {
    return netmask;
}

@JsonProperty("netmask")
public void setNetmask(String netmask) {
    this.netmask = netmask;
}

@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
    return this.additionalProperties;
}

@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
    this.additionalProperties.put(name, value);
}

 }

person Jamie Snipes    schedule 19.11.2019    source источник
comment
Привет Джейми, я знаю, что это не конкретный ответ, а просто предложение, если хотите. Я терпел перевод JSON-XML и обратно, и это боль. Не программируйте его. Вы случайно не можете использовать пакет NPM в своем проекте? Этот парень прекрасно работает: npmjs.com/package/fast-xml-parser   -  person Bruno Smaldone    schedule 22.11.2019
comment
Я думал, что это было целью Джексона?   -  person Jamie Snipes    schedule 22.11.2019


Ответы (2)


Я использовал ваши классы bean-компонентов и строку json. Почти все возможно с преобразованием, но есть некоторые проблемы. Я понял это до сих пор, если кто-то сможет получить окончательное решение, это будет здорово.

Application.java

На самом деле никаких изменений.

NetworkObject.java

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"@xsi.type", "id", "uid", "name", "display_name", "global", "comment", "application_id", "type", "ip", "access_allowed", "member", "last_ip", "first_ip", "netmask"})
public class NetworkObject {

    @JsonProperty("id")
    private Integer id;
    @JsonProperty("uid")
    private String uid;
    @JsonProperty("name")
    private String name;
    @JsonProperty("display_name")
    private String displayName;
    @JsonProperty("global")
    private Boolean global;
    @JsonProperty("comment")
    private String comment;
    @JsonProperty("application_id")
    private Integer applicationId;
    @JsonProperty("type")
    private String type;
    @JsonProperty("@xsi.type")
    // CHANGE: You cannot have same element name and attribute name, so I had to change this to xtype if someone knows how to tackle this, that will be final answer
    @JacksonXmlProperty(localName = "xtype", isAttribute = true, namespace = "http://www.w3.org/2001/XMLSchema-instance")
    private String xsiType;
    @JsonProperty("ip")
    private String ip;
    @JsonProperty("access_allowed")
    private Boolean accessAllowed;
    @JsonProperty("member")
    private List<Member> member = null;
    @JsonProperty("last_ip")
    private String lastIp;
    @JsonProperty("first_ip")
    private String firstIp;
    @JsonProperty("netmask")
    private String netmask;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    // CHANGE: We don't really need on getter setters @JsonProperty("@xsi.type")
    public String getXsiType() {
        return xsiType;
    }

    // CHANGE: We don't really need on getter setters @JsonProperty("@xsi.type")
    public void setXsiType(String xsiType) {
        this.xsiType = xsiType;
    }

    @JsonProperty("id")
    public Integer getId() {
        return id;
    }

    @JsonProperty("id")
    public void setId(Integer id) {
        this.id = id;
    }

    @JsonProperty("uid")
    public String getUid() {
        return uid;
    }

    @JsonProperty("uid")
    public void setUid(String uid) {
        this.uid = uid;
    }

    @JsonProperty("name")
    public String getName() {
        return name;
    }

    @JsonProperty("name")
    public void setName(String name) {
        this.name = name;
    }

    @JsonProperty("display_name")
    public String getDisplayName() {
        return displayName;
    }

    @JsonProperty("display_name")
    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    @JsonProperty("global")
    public Boolean getGlobal() {
        return global;
    }

    @JsonProperty("global")
    public void setGlobal(Boolean global) {
        this.global = global;
    }

    @JsonProperty("comment")
    public String getComment() {
        return comment;
    }

    @JsonProperty("comment")
    public void setComment(String comment) {
        this.comment = comment;
    }

    @JsonProperty("application_id")
    public Integer getApplicationId() {
        return applicationId;
    }

    @JsonProperty("application_id")
    public void setApplicationId(Integer applicationId) {
        this.applicationId = applicationId;
    }

    @JsonProperty("type")
    public String getType() {
        return type;
    }

    @JsonProperty("type")
    public void setType(String type) {
        this.type = type;
    }

    @JsonProperty("ip")
    public String getIp() {
        return ip;
    }

    @JsonProperty("ip")
    public void setIp(String ip) {
        this.ip = ip;
    }

    @JsonProperty("access_allowed")
    public Boolean getAccessAllowed() {
        return accessAllowed;
    }

    @JsonProperty("access_allowed")
    public void setAccessAllowed(Boolean accessAllowed) {
        this.accessAllowed = accessAllowed;
    }

    @JsonProperty("member")
    public List<Member> getMember() {
        return member;
    }

    @JsonProperty("member")
    public void setMember(List<Member> member) {
        this.member = member;
    }

    @JsonProperty("last_ip")
    public String getLastIp() {
        return lastIp;
    }

    @JsonProperty("last_ip")
    public void setLastIp(String lastIp) {
        this.lastIp = lastIp;
    }

    @JsonProperty("first_ip")
    public String getFirstIp() {
        return firstIp;
    }

    @JsonProperty("first_ip")
    public void setFirstIp(String firstIp) {
        this.firstIp = firstIp;
    }

    @JsonProperty("netmask")
    public String getNetmask() {
        return netmask;
    }

    @JsonProperty("netmask")
    public void setNetmask(String netmask) {
        this.netmask = netmask;
    }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }

}

Сетевые объекты

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"network_object"})
// CHANGE: To provide root element name
@JacksonXmlRootElement(localName = "network_objects")
public class NetworkObjects {

    @JsonProperty("network_object")
    @JacksonXmlElementWrapper(useWrapping = false)
    // CHANGE: To ignore <network_object><network_object></network_object></network_object>
    private List<NetworkObject> networkObject = null;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    @JsonProperty("network_object")
    public List<NetworkObject> getNetworkObject() {
        return networkObject;
    }

    @JsonProperty("network_object")
    public void setNetworkObject(List<NetworkObject> networkObject) {
        this.networkObject = networkObject;
    }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }

}

Main.java

public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
    ObjectMapper jsonOM = new ObjectMapper();
    String jsomn = Files.readAllLines(Paths.get("sample.json"), StandardCharsets.US_ASCII).stream().collect(Collectors.joining(""));
    Application myApp = jsonOM.readValue(jsomn, Application.class);

    ObjectMapper mapper = new XmlMapper(); 
    mapper.enable(SerializationFeature.INDENT_OUTPUT);    
    // Not writing entire object

  System.out.println(mapper.writer().writeValueAsString(myApp.getNetworkObjects()));
}

ВЫВОД

<network_objects>
  <network_object xmlns:wstxns1="http://www.w3.org/2001/XMLSchema-instance" wstxns1:xtype="networkObjectGroupDTO">
    <name>name</name>
    <display_name>displayName</display_name>
    <application_id>3</application_id>
    <type>group</type>
  </network_object>
</network_objects>
person Pasupathi Rajamanickam    schedule 22.11.2019
comment
Я считаю, что между вашим ответом и ссылкой, которую кто-то разместил выше, мы можем это получить. Я читал указанный пост, и в нем описывалось изменение wstxns1 на xmlns:xsi. - person Jamie Snipes; 22.11.2019
comment
Ссылочная переменная ns не имеет значения, это допустимый атрибут. xmlns:wstxns1 относится к XMLSchema-instance вы можете использовать wstxns1 подходящие места. Технически xmlns:wstxns1 и xmlns:xsi одинаковы. Это как имя переменной - person Pasupathi Rajamanickam; 23.11.2019
comment
Это не так, приложение, которое я отправляю, хочет xsi. - person Jamie Snipes; 25.11.2019
comment
Я считаю, что это может помочь stackoverflow.com/questions/58052669/ - person Jamie Snipes; 27.11.2019

Вы можете использовать это:

XMLInputFactory inputFactory = XMLInputFactory.newFactory();
inputFactory.setProperty("javax.xml.stream.isNamespaceAware", false);
XmlMapper xmlMapper = new XmlMapper(inputFactory);
person Daniil    schedule 12.02.2021