简体   繁体   中英

Receiving null arguments in POST requests with JSON body using Spring Boot

I know this topic has been recurring on StackOverflow, but all the questions I've seen were for misspelled names or didn't apply to my case. I'm resorting to asking personally because after all that, I can't seem to get it fixed.

I'm following a tutorial from JavaBrain's channel where he creates a simple MVC project from scratch using Spring Boot, and it's in this video when I run into the error described in the title: when I send a POST request to the server, it accepts it and processes it, but inserts null values instead of the received ones .


I'm using IntelliJ IDEA Ultimate and I generated the project from the IDE menu itself (which is the same as start.spring.io ), with Spring Web as the only dependency.

I use Postman to send the requests, where the HEADER of my POST request is "Content-type application/json".

When I do a POST with this body:

{
    "id": 9,
    "nombre": "Galán",
    "usuario": "srgalan"
}

When I do a GET:

[
    {
        "id": 1,
        "nombre": "Víctor",
        "usuario": "viictor"
    },
    {
        "id": 2,
        "nombre": "Anabel",
        "usuario": "anabeel"
    },
    {
        "id": 0,
        "nombre": null,
        "usuario": null
    },
]
  • Víctor and Anabel are already players in the system (manually declared in the service class).

I share my model, service and controller classes, as well as the pom.xml file (unmodified).

Model class:

package com.meepletic.servidor.jugador;

public class Jugador {

    private long id;
    private String nombre;  // "name"
    private String usuario; // "username"


    // Constructores        // constructor

    public Jugador() {      // "Player"

    }

    public Jugador(long id, String nombre, String usuario) {
        super();
        this.id = id;
        this.nombre = nombre;
        this.usuario = usuario;
    }


    // Getters

    public long getId() {
        return id;
    }

    public String getNombre() {
        return nombre;
    }

    public String getUsuario() {
        return usuario;
    }


    // Setters

    public void setId(long id) {
        this.id = id;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public void setUsuario(String usuario) {
        this.usuario = usuario;
    }


    // Métodos

    @Override
    public String toString() {
        return "Jugador #" + id + ": " + nombre + " (" + usuario + ")";
    }
}

Service class:

    package com.meepletic.servidor.jugador;
    
    import org.springframework.stereotype.Service;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    
    
    @Service
    public class JugadorSer {
    
        private List<Jugador> jugadores = new ArrayList<>(
                Arrays.asList(
                        new Jugador(1L, "Víctor", "viictor"),
                        new Jugador(2L, "Anabel", "anabeel")
                )
        );
    
    
        public List<Jugador> getJugadores() {
            return jugadores;
        }
    
        public Jugador getJugador(long id) {
            return jugadores.stream()
                    .filter(x -> x.getId() == id)
                    .findFirst()
                    .get();
        }
    
        public void postJugador(Jugador jugador) {
            jugadores.add(jugador);
        }
    }

Controller class:

package com.meepletic.servidor.jugador;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;



@RestController
public class JugadorCon {

    @Autowired
    private JugadorSer servicio;    // "service"


    // GET

    @GetMapping("/jugadores")
    public List<Jugador> getTodosJugadores(){
        return servicio.getJugadores();
    }

    @GetMapping("/jugadores/{id}")
    public Jugador getJugador(@PathVariable long id){
        return servicio.getJugador(id);
    }


    // POST

    @PostMapping("/jugadores/nuevo")
    public void postJugador(Jugador jugador){
        servicio.postJugador(jugador);
    }
}

pom.xml file (unmodified):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.meepletic</groupId>
    <artifactId>servidor</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Servidor 6</name>
    <description>Servidor 6</description>
    <properties>
        <java.version>17</java.version>
    </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>
    </dependencies>

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

</project>

I think the code is fine, but it is better to make sure; my intuition tells me that the problem is (or comes) from outside the IDE.

Thanks for your attention.

Best regards.

You could try adding a @RequestBody annotation to your controller. So this:

@PostMapping("/jugadores/nuevo")
public void postJugador(Jugador jugador){
    servicio.postJugador(jugador);
}

Gets turned to this:

@PostMapping("/jugadores/nuevo")
public void postJugador(@RequestBody Jugador jugador){
    servicio.postJugador(jugador);
}

The annotation basically tells spring to deserialize your input JSON into the given object (Jugador)

I was having the same problem, and to add to Fambo's answer, apparently the fields of the object (in this case Jugador) need to be private.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM