[JAVA] Deserialisieren Sie XML mit Spring-Boot in eine Sammlung

Überblick

Empfangen Sie XML in einer HTTP-Anforderung mit Spring-Boot und deserialisieren Sie es in ein Java-Objekt.

Quellcode

pom.xml

pom.xml


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>

Deserialisieren

Details werden später beschrieben, aber die Art und Weise, wie Anmerkungen geschrieben werden, ändert sich abhängig davon, ob sich der Teil, der der Java-Auflistung in XML entspricht, direkt unter dem Stammverzeichnis von XML befindet.

Wenn nicht direkt unter root

Angenommen, das folgende XML wird gesendet. Unter list </ code> befindet sich ein sich wiederholendes Element.

<sampleRoot>
	<list>
		<sampleElement>
			<id>1</id>
			<value>v1</value>
		</sampleElement>
		<sampleElement>
			<id>2</id>
			<value>v2</value>
		</sampleElement>
	</list>	
</sampleRoot>

Bereiten Sie in diesem Fall die folgende Klasse vor. Es ist keine spezielle Anmerkung erforderlich.

@Data
public class SampleRoot1 {
  List<SampleElement> list;
}
@Data
public class SampleElement {
  String id;
  String value;
}
@RestController
public class SampleController {
  @PostMapping(value = "/hoge1")
  @RequestMapping(consumes = MediaType.TEXT_XML_VALUE)
  public String hoge1(@RequestBody SampleRoot1 s) {
    System.out.println("xml body " + s);
    return "ok";
  }

Das Ausführungsergebnis sieht wie folgt aus.

xml body SampleRoot1(list=[SampleElement(id=1, value=v1), SampleElement(id=2, value=v2)])

Direkt unter der Wurzel

Angenommen, das folgende XML wird gesendet. Es gibt ein sich wiederholendes Element direkt unter root.

<sampleRoot>
	<sampleElement>
		<id>1</id>
		<value>v1</value>
	</sampleElement>
	<sampleElement>
		<id>2</id>
		<value>v2</value>
	</sampleElement>
</sampleRoot>

In diesem Fall fügen Sie @ JacksonXmlElementWrapper (useWrapping = false) `zur Sammlung hinzu, wie unten gezeigt.

package jp.co.rakuten.rmsapi.order.notice.reciever.controller;

import java.util.List;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;

import lombok.Data;

@Data
public class SampleRoot2 {
  @JacksonXmlElementWrapper(useWrapping = false)
  List<SampleElement> sampleElement;
}

Ich denke nicht, dass es eine genaue Erklärung ist, weil ich die Dokumentation nicht richtig gelesen habe, aber es scheint, dass `` `useWrapping = false``` angibt, dass diese Eigenschaft von keinem Element umgeben ist.

Ausführungsergebnis.

xml body SampleRoot2(sampleElement=[SampleElement(id=1, value=v1), SampleElement(id=2, value=v2)])

Wenn keine Anmerkung vorhanden ist, tritt der folgende Fehler auf. Der Versuch, eine Instanz von SampleElement </ code> der Liste `` `selbst zuzuordnen, ist fehlgeschlagen.

Failed to resolve argument 0 of type 'jp.co.rakuten.rmsapi.order.notice.reciever.controller.SampleRoot2' 
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `jp.co.rakuten.rmsapi.order.notice.reciever.controller.SampleElement` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('1'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `jp.co.rakuten.rmsapi.order.notice.reciever.controller.SampleElement` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('1')
 at [Source: (PushbackInputStream); line: 3, column: 8](through reference chain: jp.co.rakuten.rmsapi.order.notice.reciever.controller.SampleRoot2["sampleElement"]->java.util.ArrayList[0])
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:241)
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:223)

Abhängig von der Struktur von XML kann es erforderlich sein, @ JacksonXmlRootElement``` oder @ JacksonXmlProperty``` anzugeben, wie unten gezeigt. Es scheint auch, dass es von der Version von Jackson abhängt, so dass es scheint, dass Sie es jedes Mal überprüfen müssen.

import java.util.List;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

import lombok.Data;

@Data
@JacksonXmlRootElement(localName = "SampleRoot")
public class SampleRoot2 {
  @JacksonXmlElementWrapper(useWrapping = false)
  @JacksonXmlProperty
  List<SampleElement> sampleElement;
}

Recommended Posts