1

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?

10
  • @sunkuet02 It did help but I havnt fully solved the problem. Could you check my updated question? Commented Aug 6, 2017 at 10:28
  • 1
    Add two constructor in your Data class. One with an argument of Customer type and another is empty. Also, implements Serializable in Data class and then know us the result. Commented Aug 6, 2017 at 10:51
  • 1
    Did you update your Data Class ? with constructors ? Commented Aug 6, 2017 at 11:49
  • 1
    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 lastname. It will work. Commented Aug 6, 2017 at 16:09
  • 1
    @sunkuet02 the jsonproperty solution works! thanks! Commented Aug 6, 2017 at 16:21

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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"
    }

1 Comment

I could do that but I would like to stick to the approach using status and data. How do I pack an object in the data field?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.