Reputation: 855
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?
Upvotes: 1
Views: 3088
Reputation: 2442
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
.
N.B
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.
Upvotes: 2
Reputation: 3522
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"
}
Upvotes: 0