简体   繁体   中英

JSON POST Request getting exception on server side

I am trying to setup a Spring JPA based REST API. I am using com.fasterxml.jackson.core for processing JSON request and response. In my controller, I have a post request where I basically do create operation. The following is the code that does it:

@Autowired
    CustomerRepository repository;

    @RequestMapping(value = "/postcustomer", method = RequestMethod.POST)
    public void postCustomer(@RequestBody Customer customer) {

        repository.save(new Customer(customer.getFirstName(), customer.getLastName()));
    }

So as you can see, I need to send in my body an object of type customer. I am trying to use postman to test it and the following is the JSON I am sending to the server:

{
    "status": "Done",
    "data": [
        "Customer" : {
            "firstname" : "test",
            "lastname" : "123"
        }
    ]
}

Am I send the request wrong? Since I keep getting an exception saying:

{
"timestamp":1501908753094,
"status":400,
"error":"Bad Request",
"exception":"org.springframework.http.converter.HttpMessageNotReadableException",
"message":"JSON parse error: Unexpected character (':' (code 58)): was expecting comma to separate Array entries; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character (':' (code 58)): was expecting comma to separate Array entries\n at [Source: java.io.PushbackInputStream@6f57265c; line: 4, column: 18]",
"path":"/uzmi/postcustomer"
}

UPDATE: After changing my solution according to the answer, I have this: CustomerCOntroller.java :

import com.test.message.Response;
import com.test.repo.CustomerRepository;    
@RestController
public class CustomerController {    
    @Autowired
    CustomerRepository repository;    
    @RequestMapping(value = "/postcustomer", method = RequestMethod.POST)
    public void postCustomer(@RequestBody Response request) {
        request.getData().forEach((data) -> {
            repository.save(data.getCustomer());
        });
    }    
}

Response.java :

package com.test.message;    
import java.io.Serializable;
import java.util.List;    
public class Response implements Serializable {    
    private String status;    
    private List<Data> data;    
    public Response(String status, List<Data> data) {
        this.status = status;
        this.data = data;
    }    
    public Response() {
    }    
    public String getStatus() {
        return status;
    }    
    public void setStatus(String status) {
        this.status = status;
    }    
    public List<Data> getData() {
        return data;
    }    
    public void setData(List<Data> data) {
        this.data = data;
    }    
}

Data.java :

package com.test.message;    
import com.fasterxml.jackson.annotation.JsonProperty;
import com.test.model.Customer;    
public class Data {    
    @JsonProperty("Customer")
    private Customer customer;    
    public Customer getCustomer() {
        return customer;
    }    
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
    public Data() {
    }
    public Data(Customer customer) {
        this.customer = customer;
    }
}

But now when I try the postcontroller api using the following JSON:

{
    "status": "Done",
    "data": [ {
        "Customer": {
            "firstname" : "test",
            "lastname" : "123"
        }
    }]
}

I get the following error:

{
    "timestamp": 1502014916458,
    "status": 400,
    "error": "Bad Request",
    "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
    "message": "JSON parse error: Can not construct instance of com.test.message.Response: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.test.message.Response: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)\n at [Source: java.io.PushbackInputStream@157f2538; line: 2, column: 5]",
    "path": "/test/postcustomer"
}

UPDATE2: customer.java :

package com.test.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "customer")
public class Customer implements Serializable {
    private static final long serialVersionUID = -3009157732242241606L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @Column(name = "firstname")
    private String firstName;
    @Column(name = "lastname")
    private String lastName;
    protected Customer() {
    }
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

Any ideas where I am going wrong?

First, your given json format is not correct. I have changed in the below format.

{
    "status": "Done",
    "data": [ {
        "Customer": {
            "firstname" : "test",
            "lastname" : "123"
        }
    }]
}

If you want to accept the above json as a request body, then you need to add two more class and change the controller respectively.

Changed Controller method

@RequestMapping(value = "/postcustomer", method = RequestMethod.POST)
public void postCustomer(@RequestBody PostCustomerRequest request) {
    for(Data data : request.getData()) {
        repository.save(data.getCustomer());
    }
}

Clearly, you need PostCustomerRequest and Data class.

PostCustomerRequest class

public class PostCustomerRequest implements Serializable {
    private String status;

    private List<Data> data;

    // Respective constructor, getter and setter methods
}

Data class

public class Data {
    @JsonProperty("Customer")
    private Customer customer;

    // Respective constructor, getter and setter methods
}

Then you can post you above json .

NB

Here, you can easily notice that, the Data class has no use without wrapping Customer . You can give it up. This also minimizes your json format. If you don't want to use Data class, then use List<Customer> inside PostCustomerRequest . If so, then you json will be minimized to

{
    "status": "Done",
    "data": [ 
        {
            "firstname" : "test",
            "lastname" : "123"
        }
    ]
}

And I think everyone will suggest this format.

For last Update

You have given firstname in json, but the variable name is firstName . This is the mismatch. You can change the variable name. Better you may add @JsonProperty("firstname") above your firstName variable. Similarly do for lastname. It will work.

One more thing is that, you can convert your json to POJO in online. There are several one but I have used JSON Schema to POJO .

you dosnt need to send status , data into json, you can send only json body into request, RequestBody can map it property with the entity or pojo. you can send only parameter and value into JSON boby, you can find it below:

    {
        "firstname" : "test",
        "lastname" : "123"
    }

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