Code 400, Unrecognized field "customer" not marked as ignorable - java

My problem:
I`ve built a rest client within my iphone-application with restkit 0.20.
My RESTService was built with jax-rs including jackson.
There is one class named "Customer", where I hold my customer data.
#XmlRootElement
public class Customer extends BaseEntity {
private int customer_id;
private String appell;
private String firstname;
private String lastname;
private Date birthday;
private String street;
private String streetnr;
private String zipcode;
private String place;
public int getCustomer_id() {
return customer_id;
}
public void setCustomer_id(int customer_id) {
this.customer_id = customer_id;
}
public String getAppell() {
return appell;
}
public void setAppell(String appell) {
this.appell = appell;
}
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 Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getStreetnr() {
return streetnr;
}
public void setStreetnr(String streetnr) {
this.streetnr = streetnr;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
What can I do? Why there's always this error logged in RestKit:
Expected status code in (200-299), got 400" UserInfo=0x956e2f0 {NSLocalizedRecoverySuggestion=Unrecognized field "customer" (Class customer.model.Customer), not marked as ignorable
I don't have a field named customer.
Here is my POST method:
#POST
#Path("/insert")
#Consumes(MediaType.APPLICATION_JSON)
public Response insertCustomer(Customer customer) {
String result = "Customer inserted " + customer.getLastname();
customer.createEntity();
return Response.status(201).type(MediaType.APPLICATION_JSON).entity(result).build();
}
This is an example of a generated JSON object (Jackson), when a #GET method is called within my ios application.
{
"appell": "Frau",
"birthday": "1991-10-01T00:00:00+01:00",
"customer_id": "3",
"firstname": "Max",
"lastname": "Mustermann",
"place": "München",
"street": "Einsteinweg",
"streetnr": "19",
"zipcode": "81858"
}
And this is an example of the JSON object, when my ios application calls the showed #POST method:
{"customer":{"streetnr":"19",
"zipcode":"81829",
"customer_id":0,
"place":"München",
"appell":"Herr",
"firstname":"Heinrich",
"birthday":"1991-10-01T00:00:00+01:00",
"lastname":"Maier",
"street":"Lehrer-Wirth-Str.19"}}
I am a absolute newbie using restkit and jax-rs.
I just added a #GET method for requesting xml format.
Here you can see it:
#GET
#Path("/listallcustomers")
#Produces(MediaType.APPLICATION_XML)
public ArrayList<Customer> showAllCustomers() {
ArrayList<Customer> list = DBAccess.getInstance().getAllCustomers();
return list;
}
and this is the result:
<customers>
<customer>
<appell>Frau</appell>
<birthday>1991-10-01T00:00:00+01:00</birthday>
<customer_id>3</customer_id>
<firstname>Max</firstname>
<lastname>MUstermann</lastname>
<place>München</place>
<street>Einsteinstr.</street>
<streetnr>19</streetnr>
<zipcode>82838</zipcode>
</customer>
...
My #GET method which creates a JSON object is the following:
#GET
#Path("/listall")
#Produces(MediaType.APPLICATION_JSON)
public ArrayList<Customer> showAllJsonCustomers() {
ArrayList<Customer> list = DBAccess.getInstance().getAllCustomers();
return list;
}
and this an example of a JSON object it creates:
{
"lastname": "Müller",
"customer_id": 6,
"appell": "Herr",
"firstname": "pupsi",
"birthday": "1986-10-16",
"street": "Lehrer-Wirth-Str",
"streetnr": "19",
"zipcode": "81829",
"place": "München"
},
...

Related

Not able to wrap JSON properties in a Custom Java Class in Jackson

I have a JSON string that needs to be converted to JAVA Object. I need to wrap some fields into a different JAVA class. The problem I am facing I am not able to wrap it and I get the Java fields as null.
Please see below JSON
{
"first_name": "John",
"last_name": "DCosta",
"age": "29",
"phone": "+173341238",
"address_line_1": "43 Park Street",
"address_line_2": "Behind C21 Mall",
"city": "Cario",
"country": "UK",
"child1": {
"name": "Peter",
"age": "5"
},
"child2": {
"name": "Paddy",
"age": "2"
},
"child3": {
"name": "Premus",
"age": "1"
}
}
Please see my JAVA Classes Below -
Details.java
public class Details {
private Person person;
private Address address;
private Child[] children;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Child[] getChildren() {
return children;
}
public void setChildren(Child[] children) {
this.children = children;
}
}
Person.java
import com.fasterxml.jackson.annotation.JsonProperty;
public class Person {
#JsonProperty("first_name")
private String firstName;
#JsonProperty("last_name")
private String lastName;
#JsonProperty("age")
private Integer age;
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 Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Address.java
import com.fasterxml.jackson.annotation.JsonProperty;
public class Address {
#JsonProperty("phone")
private String phone;
#JsonProperty("address_line_1")
private String addressLine1;
#JsonProperty("address_line_2")
private String addressLine2;
#JsonProperty("city")
private String city;
#JsonProperty("country")
private String country;
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getAddressLine2() {
return addressLine2;
}
public void setAddressLine2(String addressLine2) {
this.addressLine2 = addressLine2;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
Child.java
public class Child {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
My Code to convert JSON to JAVA Object -
String filePath = "test.json";
File file = new File(filePath);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Details details = mapper.readValue(file, Details.class);
System.out.println(details.getPerson());
The problem I am facing is I am getting all the values in the details object are null. If I remove the mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); then I get the below exception
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "first_name" (class learn.springboot.model.Details), not marked as ignorable (3 known properties: "address", "person", "children"])
at [Source: (File); line: 2, column: 17] (through reference chain: learn.springboot.model.Details["first_name"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.ja
I don't think that it is possible to have some wrapper classes and expect Jackson to flatten and extract all of those fields from wrapper classes and map the flat JSON fields to them.
Based on the Details class, Jackson expects having a JSON object like the below one (inner fields are omitted):
{
"person": {},
"address": {},
"children": []
}
So, you have to change the Details class to something like below:
public class Details {
#JsonProperty("first_name")
private String firstName;
#JsonProperty("last_name")
private String lastName;
#JsonProperty("age")
private Integer age;
...
}

What is the best way to define a common Base Java Model for all Responses?

I have a need to format all REST responses as:
{
"response": {}
"status": "ERROR"
"error": {
"status": "ERROR",
"errors": [
{
"type": "ERROR",
"code": "E1001",
"message": "This is error 1.",
"reference": "TEST 1"
},
{
"type": "ERROR",
"code": "E1002",
"message": "This is error 2.",
"reference": "TEST 2"
}
]
}
}
Where the response is an arbitrary data (object, array; with arbitrary fields) different for each REST API endpoint.
What is the best way to define different response for each response Model ?
I tried this (and it works, but I'm not sure is it the right thing to do):
BaseResponseModel.java
public class BaseResponseModel {
private String status = "SUCCESS";
private List<ErrorExtendedModel> errors = new ArrayList<>();
// Various constructors, getters and setters
}
and the subclass:
CustomerResponseModel.java
public class CustomerResponseModel extends BaseResponseModel {
public List<Response> response = new ArrayList<>();
public static class Response {
private String customerId;
private String firstName;
private String lastName;
public Response(String customerId, String firstName, String lastName) {
this.customerId = customerId;
this.firstName = firstName;
this.lastName = lastName;
}
// getters and setters of inner class
}
public CustomerResponseModel() {
super();
}
public List<Response> getResponse() {
return response;
}
public void setResponse(List<Response> response) {
this.response = response;
}
}
I used inner static class with fields in every subclass but I'm not sure is it the correct way to do.
In this case I wouldn't go for inheritance but rather go for composition and leverage generics. The advantage of this approach is that you don't require nested classes, you enforce the base REST model throughout your application while keeping the response type generic.
BaseResponseModel.java:
public class BaseResponseModel<T> {
private T response;
private String status = "SUCCESS";
private List<ErrorExtendedModel> errors = new ArrayList<>();
public BaseResponseModel(T response) {
this.response = response;
}
// ...
}
CustomerResponseModel.java:
public class CustomerResponseModel {
private String customerId;
private String firstName;
private String lastName;
public CustomerResponseModel(String customerId, String firstName, String lastName) {
this.customerId = customerId;
this.firstName = firstName;
this.lastName = lastName;
}
// ...
}
Example of the usage:
public class RestApiController {
public BaseResponseModel<CustomerResponseModel> getOneCustomer(String customerId) {
return new BaseResponseModel(new CustomerResponseModel(...));
}
public BaseResponseModel<List<CustomerResponseModel>> getAllCustomers() {
return new BaseResponseModel(List.of(new CustomerResponseModel(...), new CustomerResponseModel(...)));
}
// ...
}

Spring boot REST API Missing URI template variable

I have followed this tutorial to build REST API using Spring boot. It taught alot. But What I am trying to do really got me stuck.
What I am trying to get is:
{
"marks":{
"id":"1",
"name":"test",
"remark":"passed",
"course": {
"id": "1",
"name": "Spring Boot",
"description": "Solves many problems",
"topic": {
"id": "1",
"name": "Java",
"description": "Powerful Programming Language"
}
}
But I get the error when I tried to add the marks- as :
{
"timestamp": 1515600105327,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.web.bind.MissingPathVariableException",
"message": "Missing URI template variable 'courseId' for method parameter of type String",
"path": "/topics/1/courses/1/marks"
}
My Marks Model is:
public class Marks {
#Id
private String id;
private String name;
private String remark;
#ManyToOne
private Course course;
#ManyToOne
private Topic topic;
public Marks() {
}
public Topic getTopic() {
return topic;
}
public void setTopic(Topic topic) {
this.topic = topic;
}
public Marks(String id, String name, String remark,String topicId, String courseId) {
this.id = id;
this.name = name;
this.remark = remark;
this.topic = new Topic(topicId, "","");
this.course = new Course(courseId, " ", " ", " ");
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
}
And MarksController.java:
public class MarksController {
#RestController
public class MarksController {
#Autowired
private MarksService marksService;
#RequestMapping("/topics/{topicId}/courses/{id}/marks")
public List<Marks> getAllMarks(#PathVariable String courseId) {
return marksService.getAllMarks(courseId);
}
#RequestMapping(method=RequestMethod.POST, value="/topics/{topicId}/courses{courseId}/marks")
public void addMarks(#RequestBody Marks marks,#PathVariable String topicId ,#PathVariable String courseId) {
marks.setTopic(new Topic(topicId, "", ""));
marks.setCourse(new Course(courseId, "", "", ""));
marksService.addMarks(marks);
}
}
And MarksService.java:
public class MarksService {
#Service
public class MarksService {
#Autowired
private MarksRepository marksRepository;
public void addMarks(Marks marks) {
marksRepository.save(marks);
}
}
And MarksRepository.java:
public interface MarksRepository extends CrudRepository<Marks, String> {
public List<Marks> findByCourseId(String courseId);
public List<Marks> findByTopicId(String topicId);
}
Can anyone help me get the result as in the mentioned JSON.
For the POST method
This:
/topics/{topicId}/courses{courseId}/marks
Should be:
/topics/{topicId}/courses/{courseId}/marks
Note the additional / between courses and {courseId}
For the GET method
This:
/topics/{topicId}/courses/{id}/marks
Should be:
/topics/{topicId}/courses/{courseId}/marks
Note the use of courseId to agree with the parameter name in MarksController.getAllMarks.

How to map JSONObject in Java object

I have to map this JSONObject into a Java object.
This is my Json:
{"WALLET":{
"ID":"1234",
"BAL":"20.000",
"NAME":"Filomena",
"EMAIL":"filo#gmail.com",
"DOCS":[
{
"ID":"001",
"S":"0",
"TYPE":"CardId",
"VD":"2019"
}
],
"IBANS":[
{
"ID":"001",
"S":"1",
"DATA":"iban",
"SWIFT":"swiftCode",
"HOLDER":"holder"
}
],
"STATUS":"string",
"BLOCKED":"1",
"SDDMANDATES":[
{
"ID":"sddMandateId",
"S":"status",
"DATA":"iban",
"SWIFT":"swiftCode"
}
],
"LWID":"string",
"CARDS":[
{
"ID":"string",
"EXTRA":{
"IS3DS":"string",
"CTRY":"string",
"AUTH":"string",
"NUM":"string",
"EXP":"string",
"TYP":"string"
}
}
],
"FirstName":"string",
"LastName":"string",
"CompanyName":"string",
"CompanyDescription":"string",
"CompanyWebsite":"string"
}
}
This is my Java class:
public class Wallet {
private String id;
private String bal;
private String name;
private String email;
private List<Doc> docs;
private List<Iban> ibans;
private String status;
private String blocked;
private List<SddMandate> sddMandates ;
private String lwid;
private List<Card> cards;
private String firstName;
private String lastname;
private String companyName;
private String companyDescription;
private String companyWebSite;
public Wallet(){
}
public Wallet(String id, String bal, String name, String email, List<Doc> docs, List<Iban> ibans, String status,
String blocked, List<SddMandate> sddMandates, String lwid, List<Card> cards, String firstName,
String lastname, String companyName, String companyDescription, String companyWebSite) {
super();
this.id = id;
this.bal = bal;
this.name = name;
this.email = email;
this.docs = docs;
this.ibans = ibans;
this.status = status;
this.blocked = blocked;
this.sddMandates = sddMandates;
this.lwid = lwid;
this.cards = cards;
this.firstName = firstName;
this.lastname = lastname;
this.companyName = companyName;
this.companyDescription = companyDescription;
this.companyWebSite = companyWebSite;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getBal() {
return bal;
}
public void setBal(String bal) {
this.bal = bal;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Doc> getDocs() {
return docs;
}
public void setDocs(List<Doc> docs) {
this.docs = docs;
}
public List<Iban> getIbans() {
return ibans;
}
public void setIbans(List<Iban> ibans) {
this.ibans = ibans;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getBlocked() {
return blocked;
}
public void setBlocked(String blocked) {
this.blocked = blocked;
}
public List<SddMandate> getSddMandates() {
return sddMandates;
}
public void setSddMandates(List<SddMandate> sddMandates) {
this.sddMandates = sddMandates;
}
public String getLwid() {
return lwid;
}
public void setLwid(String lwid) {
this.lwid = lwid;
}
public List<Card> getCards() {
return cards;
}
public void setCards(List<Card> cards) {
this.cards = cards;
}
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 String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getCompanyDescription() {
return companyDescription;
}
public void setCompanyDescription(String companyDescription) {
this.companyDescription = companyDescription;
}
public String getCompanyWebSite() {
return companyWebSite;
}
public void setCompanyWebSite(String companyWebSite) {
this.companyWebSite = companyWebSite;
}
Now i'm trying to map the object with gson library.
Wallet walletDetails=gson.fromJson(rispostaGetWalletDetails.toString(), Wallet.class);
System.out.println("Balance: "+walletDetails.getBal());
Now when i try to call method on the object i have always null and not the real value.
How i can do?
You have a wrong root level.
Probably, you need to need to get one level down
JSONObject yourObject = json.get("WALLET");
Wallet walletDetails = gson.fromJson(yourObject.toString(), Wallet.class);
To have Gson handle the correct field name mapping while deserializing, you have to register a FieldNamingStrategy like this (using Java 8):
Gson gson = new GsonBuilder()
.setFieldNamingStrategy(field -> field.getName().toUpperCase())
.create();
The strategy will convert each Java field name to match those in your JSON.
This will cover almost all your fields except for those upper-camel-cased in the JSON response, such as "LastName", "CompanyName", etc. In order to map those too, your FieldNamingStrategy will have to become a little bit smarter, like:
field -> {
String fname = field.getName();
return "firstName".equals(fname) || "companyName".equals(fname) /*etc...*/ ? capitalize(fname) : fname.toUpperCase();
}
and so on, I think you got the idea.
The capitalize() method you can find in libraries like Apache Commons Lang or write your own, it's just for examplification here.
Your object variable name doesn't match the json attribute name. "EMAIL" in json should have same EMAIL in object. To overcome this, you could mention #JsonProperty before your attribute declaraction.
for eg:
#JsonProperty("EMAIL")
private String email;

Convert Java nested class to JSON using JAX-RS

I basically want to send an object of class Customer as JSON to android from my JAVA REST API.
My Customer class looks like this:
public class Customer {
private long customerId;
private String firstName;
private String middleName;
private String lastName;
private String gender;
private long accountId;
class Account {
private long accountId;
private int balance;
}
}
The JSON I am expecting should look like this:
{
"customerId": "something",
"firstName": "something",
"middleName": "something",
"gender": "M or F",
"accountId": "something",
"Account": {
"accountId": "something",
"balance": "something",
}
}
Extra Information:
I use this dependency for conversion to JSON.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
How can I make an object of this class so that it's JSON conversion by JAX-RS look like this?
Outer class could have more than one inner class instance. If you want to marshall it to JSON, you should tell, what instance to use. For this, I suppose to add Account account field into outer class. Then, you need to add getters/setters for private fields and XmlElement annotations. Finally, it will look like this:
import javax.xml.bind.annotation.XmlElement;
public class Customer {
private long customerId;
private String firstName;
private String middleName;
private String lastName;
private String gender;
private long accountId;
private Account account;
class Account {
private long accountId;
private int balance;
#XmlElement(name = "accountId")
public long getAccountId() {
return accountId;
}
public void setAccountId(long accountId) {
this.accountId = accountId;
}
#XmlElement(name = "balance")
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
}
#XmlElement(name = "customerId")
public long getCustomerId() {
return customerId;
}
public void setCustomerId(long customerId) {
this.customerId = customerId;
}
#XmlElement(name = "firstName")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#XmlElement(name = "middleName")
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
#XmlElement(name = "lastName")
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#XmlElement(name = "gender")
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
#XmlElement(name = "accountId")
public long getAccountId() {
return accountId;
}
public void setAccountId(long accountId) {
this.accountId = accountId;
}
#XmlElement(name = "account")
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
}
Now, you could use instances of this class with Jersey client like this:
Entity e = Entity.entity(customer, "application/json");
Response r = invocationBuilder.method("POST", e);

Categories