i'm trying to receive response with retrofit + rxjava + gson
and our backend developed with laravel.
the problem is gson cant convert json to my java class
here is samples of my classes and responses
sample of response :
{
"data": {
"id": 3,
"name": "name",
"last_name": "last name",
"phone_number": "091212345678",
"avatar": null
}
}
and the java class :
public class User {
private Long id;
private String name;
private String last_name;
private String phone_number;
private String role;
#SerializedName("avatar")
private String profilePicture;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return last_name;
}
public void setLastName(String last_name) {
this.last_name = last_name;
}
public String getPhone_number() {
return phone_number;
}
public void setPhone_number(String phone_number) {
this.phone_number = phone_number;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getProfilePicture() {
return profilePicture;
}
public void setProfilePicture(String profilePicture) {
this.profilePicture = profilePicture;
}
i dont know what "data" in json response is.
and why gson cant convert json to java.
please help me
As this json response is nested You should design the class like below by wrapping user object inside to parse this response properly.
public class User {
public Long id;
public String name;
public String last_name;
public String phone_number;
public String avatar;
}
-----------------------------------
public class Data {
public User user;
}
Redesign your Model Class Like this:
public class User {
#SerializedName("data")
public Data data;
// Generate getter setter for all the field here
}
Now Create another class named Data with your Json property:
public class Data {
public Long id;
public String name;
public String last_name;
public String phone_number;
public String avatar;
// Generate getter setter for all the field here
}
Now you can access the fields like this:
User user = new User();
//get name
user.getData().getName();
//set name
user.getData().setName("Demo");
You have a JSON object called "data" and the User class does not contain a data field to store the contents of the "data" object. Gson is looking for a field named "data" in the User class that can hold the contents of the "data" object and isn't finding it. Now there are two ways to go about this.
Return your JSON object in this format:
{
"id": 3,
"name": "name",
"last_name": "last name",
"phone_number": "091212345678",
"avatar": null
}
OR
2.1 Create a Data class and declare it in the User class:
public class Data {
private Long id;
private String name;
private String last_name;
private String phone_number;
private String role;
#SerializedName("avatar")
private String profilePicture;
/*Getters and setters here*/ }
2.1. Declare Data field in User class
public class User { private Data data; public Data getData() { return data; }}
Related
I have a JSON response from a marvel api, i can get the copyright info from it that is in the first level, here is the response to the service:
{
"code": 200,
"status": "Ok",
"copyright": "© 2019 MARVEL",
"attributionText": "Data provided by Marvel. © 2019 MARVEL",
"attributionHTML": "Data provided by Marvel. © 2019 MARVEL",
"etag": "a1d8666dc86abda3bd2edf99d09446da82626c4b",
"data": {
"offset": 0,
"limit": 20,
"total": 1,
"count": 1,
"results": [
{
"id": 1009664,
"name": "Thor",
"description": "As the Norse God of thunder and lightning, Thor wields one of the greatest weapons ever made, the enchanted hammer Mjolnir. While others have described Thor as an over-muscled, oafish imbecile, he's quite smart and compassionate. He's self-assured, and he would never, ever stop fighting for a worthwhile cause.",
.
.
.
}
I have my getters and setters like this:
private int id;
private String name;
private String description;
private String thumbnail;
private String copyright;
public Heroe() {}
public Heroe(String copyright, int id, String name, String description, String thumbnail) {
this.copyright = copyright;
this.id = id;
this.name = name;
this.description = description;
this.thumbnail = thumbnail;
}
but i want to get the result from the data. to get the id, name, and description, here is my code:
Android response service from MARVEL
Since the json response has a child node try to Create a custom response like
HeroResponse.java
class HeroResponse {
private int code;
private String status;
//.. other variables
#SerializedName("data")
private Hero data
//.. Getter and setter
}
Hero.java
class Hero {
private int offset;
private int limit;
//.. other variables
#SerializedName("results")
private HeroDetail results
//.. Getter and setter
}
HeroDetail.java
class HeroDetail {
private int id;
private String name;
private String description
//.. Getter and setter
}
then on your retrofit call
heroeCall.enqueue(
//..
public void onResponse(Call<HeroResponse> call, Response<HeroResponse> response) {
HeroResponse resp = response.body();
resp.copyright
resp.data.offset
resp.data.results.id
}
)
Also don't forget to implement the 'com.google.code.gson:gson:2.8.5' in your app build.gradle if you want to use the annotation SerializedName
Hope this will help.
First create getter() and setter() methods in model class
Example :-
public class RetroPhoto {
#SerializedName("id")
private Integer id;
#SerializedName("title")
private String title;
#SerializedName("item")
public Item a;
public RetroPhoto(Integer albumId, Integer id, String title, String url, String thumbnailUrl) {
this.albumId = albumId;
this.id = id;
this.title = title;
this.url = url;
this.thumbnailUrl = thumbnailUrl;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Item getItem11() {
return a;
}
public void setItem11(Item item11) {
this.a = item11;
}
public class Item{
#SerializedName("id_item")
private String idItem;
#SerializedName("id_subcategory")
private String idSubcategory;
public String getIdItem() {
return idItem;
}
public void setIdItem(String idItem) {
this.idItem = idItem;
}
public String getIdSubcategory() {
return idSubcategory;
}
public void setIdSubcategory(String idSubcategory) {
this.idSubcategory = idSubcategory;
}
}
}
How to get idSubcategory :-
RetroPhoto.Item ri = response.getItem11();
String idSubcategory = ri.getIdSubcategory();
The reason for this is in my Selenium tests, I am mocking the REST services to return POJOs with hardcoded values, which represents my dummy data. One of the pages requires a list of objects who has heaps of fields and children Java objects (think Person has List, List, etc.).
A quick way I did was generate a JSON string from one of the REST services that pulls from the database. So now, I have a JSON string which I saved as a file and can load into my Selenium test as my hardcoded data. However, I want to maintain this in the Java code rather than a separate file, the data.json file.
Is there a way to generate Java code, which is basically lines and lines of setters where the values come from the JSON? I am trying to avoid having to hand-code each setter for each fields....
Example json file (in reality it has more fields and more children...):
{
"personEntity":{
"name":"xxx",
"dob":"2000-01-01",
"address":[
{
"id":"1",
"line1":"123"
},
{
"id":"2",
"line1":"zzz"
}
],
"phones":[
{
"id":"1",
"number":"999-999-999"
}
]
}
}
Desired Java code that is auto-generated:
Person p = new Person();
p.setName("xxx");
p.setDob("2000-01-01");
Address a1 = new Address();
a1.setId(1);
a1.setLine1("123")
p.addAddress(a1);
// and so on for the other fields
NOTE:
The POJOs are already existing and are NOT needed to be auto-generated. The only auto-generated code I am looking for is the sample above such as p.setName("xxx") and so on for the other fields.
Do your mean JSON -> JAVA Bean?
You can use this website json2javapojo
then you can use JSON utils to parse.
package ;
public class Address {
private String id;
private String line1;
public void setId(String id){
this.id = id;
}
public String getId(){
return this.id;
}
public void setLine1(String line1){
this.line1 = line1;
}
public String getLine1(){
return this.line1;
}
}
package ;
public class Phones {
private String id;
private String number;
public void setId(String id){
this.id = id;
}
public String getId(){
return this.id;
}
public void setNumber(String number){
this.number = number;
}
public String getNumber(){
return this.number;
}
}
package ;
import java.util.List;
public class PersonEntity {
private String name;
private String dob;
private List<Address> address ;
private List<Phones> phones ;
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setDob(String dob){
this.dob = dob;
}
public String getDob(){
return this.dob;
}
public void setAddress(List<Address> address){
this.address = address;
}
public List<Address> getAddress(){
return this.address;
}
public void setPhones(List<Phones> phones){
this.phones = phones;
}
public List<Phones> getPhones(){
return this.phones;
}
}
package ;
public class Root {
private PersonEntity personEntity;
public void setPersonEntity(PersonEntity personEntity){
this.personEntity = personEntity;
}
public PersonEntity getPersonEntity(){
return this.personEntity;
}
}
You need to de-serialize the returned JSON to java object using any of the parsers like GSON, Jackson, JSON simple etc.
Some online tools available to do your job very simple.
You can use jsonschema2pojo
-----------------------------------com.example.Address.java-----------------------
package com.example;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"id",
"line1"
})
public class Address {
#JsonProperty("id")
private String id;
#JsonProperty("line1")
private String line1;
#JsonProperty("id")
public String getId() {
return id;
}
#JsonProperty("id")
public void setId(String id) {
this.id = id;
}
#JsonProperty("line1")
public String getLine1() {
return line1;
}
#JsonProperty("line1")
public void setLine1(String line1) {
this.line1 = line1;
}
}
and so on....
I have seen multiple answers to this problem in stackoverflow and outside. But I am not able to understand the real issue here.
I have a pojo class which is given below.
public class User{
private int id;
private String name;
private String houseNumber;
private String location;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String gethouseNumber() {
return houseNumber;
}
public void sethouseNumber(String houseNumber) {
this.houseNumber = houseNumber;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
I have a JSON file as follows:
[{
"id":1,
"name": "roy",
"houseNumber":"No/242",
"location" :"Germany"
},
{
"id":2,
"name": "philip",
"houseNumber":"No/252",
"location" :"Germany"
}]
Every json entry of the file has the field location with a value. But why am I getting the exception Unrecognized field "location" inspite of having the field in both my POJO and the JSON file? I would like to know the reason of this. Many solutions suggest using annotations for JSON like #JsonIgnoreProperties. It did not work for me.
Try using camel case correctly on your getters and setters, I know that does sometimes cause Jackson to produce unexpected results.
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHouseNumber() {
return houseNumber;
}
public void setHouseNumber(String houseNumber) {
this.houseNumber = houseNumber;
}
I tried your code and it works fine for me
The #JsonIgnoreProperties is not required. you can do the following
String jsonString = "[{\"id\":1,\"name\": \"roy\",\"houseNumber\":\"No/242\",\"location\" :\"Germany\"},{\"id\":2,\"name\": \"philip\",\"houseNumber\":\"No/252\",\"location\" :\"Germany\"}]";
ObjectMapper mapper = new ObjectMapper();
List<User> a = mapper.readValue(jsonString, new TypeReference<ArrayList<User>>() {});
I would like to convert the following string/ JSONObject to POJO,
{"list":["\r\n{\r\n\"id\":\"1\",\r\n\"protocol\":\"udp\",\r\n\"srcPorts= \":\"3000-4000 \",\r\n\"destPorts\":\"1790-2000\"\r\n}","\r\n{\r\n\"id\":\"2\",\r\n \"protocol\":\"tcp\",\r\n\"srcPorts\":\"3000-4000\",\r\n\"destPorts\":\"1790-2000 \"\r\n}"],"user":"\r\n{\r\n\"name\":\"John\",\r\n\"address\":\"x.x.x.x\",\r\n\"email \":\"john#p.com\"\r\n}"}
How do I convert to Pojo using Jackson ObjectMapper.
The 2 Pojo classes are as follows.
The user part in the string above should map to the java file - User.java
public class User
{
private String name;
private String address;
private String email;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAddress()
{
return address;
}
public void setaddress(String Address)
{
this.address = address;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
}
The List part in the string above should map to the java file - TestCase.java
public class TestCase
{
private String id;
private String protocol;
private String srcPorts;
private String destPorts;
public String getProtocol()
{
return protocol;
}
public void setProtocol(String protocol)
{
this.protocol = protocol;
}
public String getSrcPorts()
{
return srcPorts;
}
public void setSrcPorts(String srcPorts)
{
this.srcPorts = srcPorts;
}
public String getDestPorts()
{
return destPorts;
}
public void setDestPorts(String destPorts)
{
this.destPorts = destPorts;
}
public String getID()
{
return id;
}
public void setID(String id)
{
this.id = id;
}
}
Following code should help.
class ParseJson{
private User user;
private TestCase testCase;
//getter and setter methods
}
//and then call objectMapper -
String jsonString = "";//Json input
ObjectMapper mapper = new ObjectMapper();
ParseJson parsedJson = mapper.readValue(jsonString, ParseJson.class);
User user = parsedJson.getUser();
TestCase testCase = parsedJson.getTestCase();
Since your JSON object does not contain any type information, the best approach would be to use a custom deserializer class for Jackson, at least for the outer class. Alternatively, you can try annotating your POJO classes with Jackson annotations, and hope that the Right Thing happens.
In any case, you will have to make Jackson aware of your context by calling one of the ObjectMapper.readValue() methods with the proper class type argument, so that Jackson will know what it is that is being deserialized.
I want to see is there a better way to achieve this: currently, I have a User class, UserRequest class and UserResponse class, they are all very similar or subset of User.
class User{
long id;
String name;
String password;
String field1;
String[] array1;
}
class UserRequest{
String name;
String password;
}
class UserResponse{
long id;
String name;
String field1;
}
So instead of having 3 similar classes, can I limit the fields using User class for the ResponseEntity? or what would be a better way to achieve what i am trying to do without having all the similar classes?
public #ResponseBody ResponseEntity<UserResponse> login(#RequestBody #Valid UserRequest request) {
User user = userRep.findByPrimaryEmailLike(request.getPrimaryEmail());
return new ResponseEntity<UserResponse>(user.getSuccessLoginResponse(), HttpHeaderUtils.getHeader4Json(), HttpStatus.OK);
}
Depends on what your format and (de-)serialization handler is, but making the wild guess it's JSON via Jackson:
import org.codehaus.jackson.annotate.JsonIgnore;
class User {
long id;
String name;
String password;
String field1;
String[] array1;
#JsonIgnore
public String[] getArray1() {
return array1;
}
#JsonIgnore
public void setArray1(String[] array1) {
this.array1 = array1;
}
public String getField1() {
return field1;
}
#JsonIgnore
public void setField1(String field1) {
this.field1 = field1;
}
public long getId() {
return id;
}
#JsonIgnore
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#JsonIgnore
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
If you use a SpringMVC extension like Yoga, you can return only the User object, but customize the request to determine which fields are returned in the #ResponseBody. For example,
GET http://mydomain.com/user?selector=name,password
GET http://mydomain.com/user?selector=id,name,field1