web-dev-qa-db-de.com

Versuch, Spring Boot zu verwenden REST JSON-String aus lesen POST

Ich benutze die neueste Version von Spring Boot, um einen Beispiel-JSON über Restful Web Service einzulesen ...

Hier ist meine pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.Apache.org/POM/4.0.0"       
         xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 
         http://maven.Apache.org/maven-v4_0_0.xsd"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>myservice</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.2.RELEASE</version>
    </parent>

    <properties>
        <Java.version>1.7</Java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-rest-webmvc</artifactId>
        </dependency>
        <dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
        <repository>
            <id>org.jboss.repository.releases</id>
            <name>JBoss Maven Release Repository</name>
            <url>https://repository.jboss.org/nexus/content/repositories/releases</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>https://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>

</project>

Hier ist mein Webservice-Code:

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/myservice")
public class BaseService {  

    @RequestMapping(value="/process", method = RequestMethod.POST)
    public void process(@RequestBody String payload) throws Exception {
        System.out.println(payload);
    }
}

Wenn ich es mit dem folgenden Befehl aufrufe:

curl -H "Accept: application/json" -H "Content-type: application/json" 
-X POST -d '{"name":"value"}' http://localhost:8080/myservice/process

Ich bekomme diese Fehlermeldung:

{"timestamp":1427515733546,"status":400,
 "error":"Bad Request",

"exception":
"org.springframework.http.converter.HttpMessageNotReadableException","
 message":
 "Could not read JSON: Can not deserialize instance of Java.lang.String
  out of START_OBJECT token\n at 

 [Source: [email protected]; line: 1, column: 1]; 
  nested    exception is com.fasterxml.jackson.databind.JsonMappingException:
  Can not deserialize instance of Java.lang.String out of START_OBJECT token\n    
  at [Source: [email protected]; line: 1, column: 1]",
  "path":"/myservice/process"

Das einzige, was ich zu tun versuche, ist eine gültige JSON (als String über curl) zu übergeben und zu sehen, ob die String-Payload die Prozessmethode als {"name": "value"} angibt

Was mache ich möglicherweise falsch?

Vielen Dank, dass Sie sich die Zeit genommen haben, dies zu lesen ...

46
PacificNW_Lover

Ich denke, der einfachste/praktischste Weg zum Konsumieren von JSON ist die Verwendung einer Java-Klasse, die Ihrem JSON ähnelt: https://stackoverflow.com/a/6019761

Wenn Sie keine Java-Klasse verwenden können, können Sie eine dieser beiden Lösungen verwenden.

Lösung 1: Sie können einen Map<String, Object> von Ihrem Controller erhalten:

@RequestMapping(
    value = "/process", 
    method = RequestMethod.POST)
public void process(@RequestBody Map<String, Object> payload) 
    throws Exception {

  System.out.println(payload);

}

Verwenden Sie Ihre Anfrage:

curl -H "Accept: application/json" -H "Content-type: application/json" \
-X POST -d '{"name":"value"}' http://localhost:8080/myservice/process

Lösung 2: Andernfalls können Sie die POST - Nutzlast als String erhalten:

@RequestMapping(
    value = "/process", 
    method = RequestMethod.POST,
    consumes = "text/plain")
public void process(@RequestBody String payload) throws Exception {

  System.out.println(payload);

}

Dann analysieren Sie den String wie gewünscht. Beachten Sie, dass auf Ihrem Controller consumes = "text/plain" angegeben werden muss ..__ In diesem Fall müssen Sie Ihre Anforderung mit Content-type: text/plain ändern:

curl -H "Accept: application/json" -H "Content-type: text/plain" -X POST \
-d '{"name":"value"}' http://localhost:8080/myservice/process
79
Andrea

Zum Hinzufügen zu Andreas Lösung, wenn Sie beispielsweise ein Array von JSONs übergeben

[
    {"name":"value"},
    {"name":"value2"}
]

Dann müssen Sie den Spring Boot Controller wie folgt einrichten:

@RequestMapping(
    value = "/process", 
    method = RequestMethod.POST)
public void process(@RequestBody Map<String, Object>[] payload) 
    throws Exception {

    System.out.println(payload);

}
2
S. Pan

Das Problem tritt auf, wenn der JSON aus dem Anforderungstext analysiert wird, was für einen ungültigen JSON typisch ist. Wenn Sie curl unter Windows verwenden, versuchen Sie, den json wie -d "{"name":"value"}" oder sogar -d "{"""name""":"value"""}" zu umgehen.

Auf der anderen Seite können Sie den Inhaltstypheader weglassen. In diesem Fall wird die Benachrichtigung gesendet, die in Ihr String-Argument konvertiert wird

2
Master Slave

Für die weitere Arbeit mit einem Array von Karten können die folgenden Informationen hilfreich sein:

@RequestMapping(value = "/process", method = RequestMethod.POST, headers = "Accept=application/json")
public void setLead(@RequestBody Collection<? extends Map<String, Object>> payload) throws Exception {

  List<Map<String,Object>> maps = new ArrayList<Map<String,Object>>();
  maps.addAll(payload);

}
0
Rusli Usman