I am trying below code to convert below JSON to POJO using ObjectMapper class of Jackson but it's throwing exception. Could anyone help me to resolve this issue.
Actually JSON is given by UI so can't change format of it. I need to parse this JSON to java object using Jackson library.
JSON: data.json
{
"0": {
"location": "6",
"userType": "1",
"isActive": "1",
"userId": "Shailesh#gmail.com"
},
"1": {
"location": "7",
"userType": "2",
"isActive": "1",
"userId": "Vikram#gmail.com"
}
}
DTOs:
public class UsersList {
List<UserDetails> users;
}
public class UserDetails {
private String userId;
private String location;
private String userType;
private String isActive;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
public String getIsActive() {
return isActive;
}
public void setIsActive(String isActive) {
this.isActive = isActive;
}
}
Test Class: HandlerUtil
import java.io.IOException;
import java.io.InputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mcmcg.ams.lambda.model.UserDetails;
public class HandlerUtil {
private static final Logger LOG = LogManager.getLogger(HandlerUtil.class);
private HandlerUtil() {
}
public static void main(String[] args) {
try (InputStream instream = HandlerUtil.class.getClassLoader().getResourceAsStream("data.json")) {
UserDetails sample = new ObjectMapper().readValue(instream, UsersList.class);
System.out.println(sample.toString());
} catch (IOException ex) {
LOG.error("Exception occurred while laoding data.json file : ", ex);
}
}
}
Exception:
com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
You can use ObjectMapper.readValue() method of jackson.
I think your solution will be like this :
String jsonBody = yourJson;
ObjectMapper objectMapper = new ObjectMapper();
try {
UserDetailsMapDao userDetailsMapDao = objectMapper
.readValue(jsonBody, UserDetailsMapDao.class);
} catch (JsonParseException e) {
// TODO Exception Handling
} catch (JsonMappingException e) {
// TODO Exception Handling
} catch (IOException e) {
// TODO Exception Handling
}
Your Daos will be like this :
public class UserDetailsMapDao {
private Map<String, UserDetails> userDetailsMap;
public String getUserDetailsMap() {
return userDetailsMap;
}
public void setUserDetailsMap(String userDetailsMap) {
this.userDetailsMap = userDetailsMap;
}
}
public class UserDetails {
private String userId;
private String location;
private String userType;
private String isActive;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
public String getIsActive() {
return isActive;
}
public void setIsActive(String isActive) {
this.isActive = isActive;
}
}
The JSON is in format of Map<String, UserDetails> take a look at that, key 0 has user "Shailesh#gmail.com" and key 1 with "Vikram#gmail.com"
TypeReference<HashMap<String,UserDetails>> typeRef
= new TypeReference<HashMap<String,UserDetails>>() {};
HashMap<String,UserDetails> sample = new ObjectMapper()
.readValue(instream, typeRef);
If using jackson use #JsonAnySetter
public class UsersList {
private Map<String, UserDetails> users = new HashMap<>();
#JsonAnySetter
public void setUsers(String name, UserDetails value) {
this.addressDetails.put(name, value);
}
}
And then map it to UserDetails
UserDetails sample = new ObjectMapper().readValue(instream, UsersList.class);
Firstly, before you can deserialize your json string to DTOs, the DTOs should contain no-argument constructor, getters and setters.
Your currect DTOs would match a string like the one below.
{
"users": [
{
"location": "6",
"userType": "1",
"isActive": "1",
"userId": "Shailesh#gmail.com"
},
{
"location": "7",
"userType": "2",
"isActive": "1",
"userId": "Vikram#gmail.com"
}
]
}
The DTO that would match the string example provided above would be like the following.
public class UsersList {
UserDetails zero;
UserDetails one;
public UsersList() {
}
public UserDetails getZero() {
return zero;
}
public void setZero(final UserDetails zero) {
this.zero = zero;
}
public UserDetails getOne() {
return one;
}
public void setOne(final UserDetails one) {
this.one = one;
}
}
Related
I have been fighting with Retrofit 2.3 for about 2 weeks now. The List always comes back as empty for me. It simply makes a call and gets the JSON information yet it won't process the list.
Json appears like this:
{
"users": [
{
"id": 2,
"name": "Users Name",
"username": "myusername",
"facebook_id": null,
"level": "1",
"birthdate": "1999-09-09T00:00:00+00:00",
"email": "user#gmail.com",
"activated": "",
"created": "2017-12-07T04:18:30+00:00",
"answers": [
{
"id": 31,
"question_id": 2,
"user_id": 2,
"answer": "School",
"questions": [
{
"id": 2,
"question": "Where did you meet your best friend?"
}
]
},
{
"id": 32,
"question_id": 3,
"user_id": 2,
"answer": "Dog",
"questions": [
{
"id": 3,
"question": "What was your first pet's name?"
}
]
}
]
}
],
"message": "Success"
}
Retrofit Interface class:
public interface RestInterface {
String url = "http://myurl.com";
/**
* Login
*
* #param username Username
* #param password Password
*
*/
#FormUrlEncoded
#Headers("User-Agent:My-Application")
#POST("login")
Call<userlogin> Login(#Field("username") String username,
#Field("password") String password);
}
Userlogin class:
public class userlogin {
#SerializedName("users")
#Expose
private List<users> users;
#SerializedName("message")
#Expose
private Object message;
public List<users> getUsers() {
return users;
}
public void setUsers(List<users> users) {
this.users = users;
}
public Object getMessage() {
return message;
}
public void setMessage(Object message) {
this.message = message;
}
}
users class:
public class users {
#SerializedName("id")
#Expose
private Integer id;
#SerializedName("name")
#Expose
private String name;
#SerializedName("username")
#Expose
private String username;
#SerializedName("facebook_id")
#Expose
private String facebookId;
#SerializedName("level")
#Expose
private String level;
#SerializedName("birthdate")
#Expose
private String birthdate;
#SerializedName("email")
#Expose
private String email;
#SerializedName("activated")
#Expose
private String activated;
#SerializedName("created")
#Expose
private String created;
#SerializedName("answers")
#Expose
private List<Answer> answers = null;
public users(){
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFacebookId() {
return facebookId;
}
public void setFacebookId(String facebookId) {
this.facebookId = facebookId;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public String getBirthdate() {
return birthdate;
}
public void setBirthdate(String birthdate) {
this.birthdate = birthdate;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getActivated() {
return activated;
}
public void setActivated(String activated) {
this.activated = activated;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
public List<Answer> getAnswers() {
return answers;
}
public void setAnswers(List<Answer> answers) {
this.answers = answers;
}
}
Basically what happens is when it is called my "message" part comes back "Successful" which on my PHP side basically just states there were no errors. If there were any then it would return the error for display.
When trying to get the users information it always comes back with an empty List.
My response is always the same:
03-14 20:06:26.698 30995-30995/com.josh.testapp D/Response: {"message":"Success","users":[]}
03-14 20:06:26.699 30995-30995/com.josh.testapp I/System.out: Users:: []
03-14 20:06:26.699 30995-30995/com.josh.testapp D/Message: Success
I'm not sure what it is I'm missing. The users should be coming back as a list containing user information, in this case just the information of the user logging in. But in other parts, this will display sub-users information as well which is why it is in List form in the first place.
Please help or guide me in the right direction.
login.java (where the call is made)
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(RestInterface.url)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
RestInterface restInterface = retrofit.create(RestInterface.class);
Call<userlogin> call = restInterface.Login(
username.getText().toString(), // username
pass.getText().toString() // password
);
call.enqueue(new Callback<userlogin>() {
#Override
public void onResponse(Call<userlogin> call, retrofit2.Response<userlogin> response) {
if (response.isSuccessful()) {
userlogin ul = response.body();
try{
String res = new Gson().toJson(response.body());
Log.d("Response", res);
System.out.println("Users:: " + ul.getUsers().toString());
Log.d("Message", ul.getMessage().toString());
List<users> userList = ul.getUsers();
for(int i = 0; i < userList.size(); i++){
Log.d("Users", userList.get(i).getUsername());
}
} catch (Exception e){
Log.d("exception", e.getMessage());
}
} else {
Log.d("unSuccessful", response.message());
}
}
#Override
public void onFailure(Call<userlogin> call, Throwable t) {
Log.d("onFailure", t.getMessage());
}
});
After AbdulAli pointed out that it appeared to not be receiving the users list I decided to look over my code and run a few more tests on the server API. I discovered there was an issue with sessions. They weren't picking up and therefor returned a "Successful" yet empty user list. After implementing some CookieJar functions in I was able to pass my cookie for sessions and the user list was no longer empty.
While I feel like an idiot for missing something so obvious, I am very grateful for you pointing that out AbdulAli.
I've a JSON which I want to deserialize to java object. I tried but failed to succeed. Really appreciate if somebody help it. I was getting below error.
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
// Note : vairable 'body' is the JSON string which I've shared below.
RpcResponse rs = mapper.readValue(body, RpcResponse.class);
Exception in thread "main"
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot
deserialize instance of Result out of START_ARRAY token
{
"error": null,
"id": "12345",
"result": {
"inventory": [{
"history": [{
"when": "2012-08-30T07:28:51Z",
"changes": [{
"removed": "",
"added": "1",
"field_name": "qty"
},
{
"removed": "normal",
"added": "major",
"field_name": "popularity"
}],
"id": 474599,
"alias": null
}]
}
}
Here are the java classes
public class RpcResponse {
private String error;
private String id;
private Map<String, Result> result;
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Result getResult() {
return result;
}
public void setResult(Result result) {
this.result = result;
}
}
public class Result {
private Map<String, List<Inventory>> inventory;
public Map<String, List<Inventory>> getBugs() {
return inventory;
}
public void setBugs(Map<String, List<Inventory>> inventory) {
this.inventory = inventory;
}
}
public class Inventory {
private String id;
private String alias;
private Map<String, List<History>> history;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public Map<String, List<History>> getHistory() {
return history;
}
public void setHistory(Map<String, List<History>> history) {
this.history = history;
}
}
public class History {
private String who;
private String when;
private Map<String, Changes> changes;
public String getWho() {
return who;
}
public void setWho(String who) {
this.who = who;
}
public String getWhen() {
return when;
}
public void setWhen(String when) {
this.when = when;
}
public Map<String, Changes> getChanges() {
return changes;
}
public void setChanges(Map<String, Changes> changes) {
this.changes = changes;
}
}
In RCP Response,
private Map<String, Result> result;
should just be
private Result result;
In Result,
private Map<String, List<Inventory>> inventory;
should be
private List<Inventory> inventory;
and in Inventory,
private Map<String, List<History>> history;
should be
private List<History> history;
In History, Map<String,Changes> should be a Collection<Changes>, etc
This question already has answers here:
Retrofit 2: Get JSON from Response body
(14 answers)
Closed 5 years ago.
How to read this response from retrofit and store to java class and access somewhere ??
{
"user": {
"__v": 0,
"updated_at": "2017-11-08T12:07:46.729Z",
"created_at": "2017-11-08T12:07:46.729Z",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRlc3QzIiwidXNlcmlkIjozLCJlbWFpbCI6ImFydWwzQHRlc3QuY29tIiwiYWNjZXNzX2xldmVsIjoiQWRtaW4iLCJfaWQiOiI1YTAyZjM5Mjk5OGM4OTI3MjQxYTQ3N2YiLCJncm91cHMiOlt7ImlkIjoxLCJuYW1lIjoiZGlhbGVyIiwiX2lkIjoiNThiM2JmODI5ZTg2MDFjMDVlNzIxNjI3In1dfQ.VKEt1JoXoL_xfRDrrFK-jVj8zC23j4sqZTT2S3HGMbc",
"username": "test3",
"userid": 3,
"email": "arul3#test.com",
"access_level": "Admin",
"_id": "5a02f392998c8927241a477f",
"groups": [{
"id": 1,
"name": "dialer",
"_id": "58b3bf829e8601c05e721627"
}]
}
}
Create classes from pojo like that then parse to retrofit Convert json response to classes
public class MyPojo{
private User user;
public User getUser ()
{
return user;
}
public void setUser (User user)
{
this.user = user;
}
}
User Class:
public class User{
private String username;
private String updated_at;
private String _id;
private String access_level;
private String email;
private String token;
private String userid;
private String __v;
private String created_at;
private Groups[] groups;
public String getUsername ()
{
return username;
}
public void setUsername (String username)
{
this.username = username;
}
public String getUpdated_at ()
{
return updated_at;
}
public void setUpdated_at (String updated_at)
{
this.updated_at = updated_at;
}
public String get_id ()
{
return _id;
}
public void set_id (String _id)
{
this._id = _id;
}
public String getAccess_level ()
{
return access_level;
}
public void setAccess_level (String access_level)
{
this.access_level = access_level;
}
public String getEmail ()
{
return email;
}
public void setEmail (String email)
{
this.email = email;
}
public String getToken ()
{
return token;
}
public void setToken (String token)
{
this.token = token;
}
public String getUserid ()
{
return userid;
}
public void setUserid (String userid)
{
this.userid = userid;
}
public String get__v ()
{
return __v;
}
public void set__v (String __v)
{
this.__v = __v;
}
public String getCreated_at ()
{
return created_at;
}
public void setCreated_at (String created_at)
{
this.created_at = created_at;
}
public Groups[] getGroups ()
{
return groups;
}
public void setGroups (Groups[] groups)
{
this.groups = groups;
}
}
Groups Class:
public class Groups{
private String id;
private String _id;
private String name;
public String getId ()
{
return id;
}
public void setId (String id)
{
this.id = id;
}
public String get_id ()
{
return _id;
}
public void set_id (String _id)
{
this._id = _id;
}
public String getName ()
{
return name;
}
public void setName (String name)
{
this.name = name;
}}
Now follow that put your classes and get desire response Retrofit Json response
Given the below json
{
"countries":{
"country":[{
"name":"USA",
"independence":"July 4, 1776",
}],
},
}
I will like to ignore "countries" and get the value of country instead. hence, after mapping my json should look as so
{
"countries": [{
"name":"USA",
"independence":"July 4, 1776",
}],
}
Is this currently possible with ObjectMapper?
EDIT: below are the Pojo
public class Result {
private static final long serialVersionUID = 6403654749443599206L;
#Getter #Setter #JsonProperty("country") private List<Country> countries;
}
public class Country {
private static final long serialVersionUID = 6403654749443599206L;
#Getter #Setter private String name;
#Getter #Setter private String independence;
}
and I am doing this
return new ObjectMapper().readValue({jsonValue}, Result.class);
The input json has a wrong syntax. It should be like this
{
"countries":{
"country":[{
"name":"USA",
"independence":"July 4, 1776"
}]
}
}
ObjectMapper is used to turn json into Object and Object into json. Anyway, to convert the first json to the other you desire you can do something like this:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.IOException;
import java.util.List;
public class ConvertExample {
public static void main(String[]args) {
String inputJson = new String("{\"countries\":{\"country\":[{\"name\":\"USA\", \"independence\":\"July 4, 1776\"}]}}");
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT); //To indent output, optional
try {
StartPojo startPojo = mapper.readValue(inputJson, StartPojo.class);
EndPojo endPojo = new EndPojo();
endPojo.countries = startPojo.getCountries().getCountry();
String outputJson = mapper.writeValueAsString(endPojo);
System.out.println("Output:");
System.out.println(outputJson);
} catch (IOException e) {
e.printStackTrace(); //Cannot read the input json
}
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class StartPojo {
private Countries countries;
public Countries getCountries() {
return countries;
}
public void setCountries(Countries countries) {
this.countries = countries;
}
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class EndPojo {
private List<Country> countries;
public List<Country> getCountries() {
return countries;
}
public void setCountries(List<Country> countries) {
this.countries = countries;
}
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Countries {
private List<Country> country;
public List<Country> getCountry() {
return country;
}
public void setCountry(List<Country> country) {
this.country = country;
}
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Country {
private String name;
private String independence;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIndependence() {
return independence;
}
public void setIndependence(String independence) {
this.independence = independence;
}
}
}
This class takes the input json and convert it to the other format by printing it into the console. The ouput of this code is:
{
"countries" : [ {
"name" : "USA",
"independence" : "July 4, 1776"
} ]
}
I'm encountering problem with my android app for REST service.
I got following json response from server:
{
"0": {
"id": 1,
"name": "Some Guy",
"email": "example1#example.com"
},
"1": {
"id": 2,
"name": "Person Face",
"email": "example2#example.com"
},
"3": {
"id": 3,
"name": "Scotty",
"email": "example3#example.com",
"fact": {
"hobbies": ["fartings", "bikes"]
}
}
}
My objects are:
User class:
public class User {
#SerializedName("id")
private
int id;
#SerializedName("name")
private
String name;
#SerializedName("email")
private
String email;
#SerializedName("fact")
private
Fact fact;
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Fact getFact() {
return fact;
}
public void setFact(Fact fact) {
this.fact = fact;
}
public User(){}
}
Fact class:
public class Fact {
#SerializedName("hobbies")
private List<Hobbies> hobbies;
public List<Hobbies> getHobbies() {
return hobbies;
}
public void setHobbies(List<Hobbies> hobbies) {
this.hobbies = hobbies;
}
public Fact(){}
}
Hobbies class:
public class Hobbies {
private String hobby;
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public Hobbies(){}
}
When I use below code in my app:
private User jsonToUser(String result){
User users = null;
if(result != null && result.length() > 0){
Gson gson = new GsonBuilder().create();
users = gson.fromJson(result, User.class);
}
return users;
}
Object returned by function is filled by nulls. I've tried to use class Users which is empty and extends ArrayList
public class Users extends ArrayList<User> {
//
}
and app was giving me error:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2
I wish to use it for:
ArrayAdapter<User> adapter = new ArrayAdapter<User>(activity, android.R.layout.simple_list_item_1, users);
Could you tell me what I'm doing wrong, please? It worked for my twitter timeline app, but doesn't wor for this.
Your code users = gson.fromJson(result, User.class); would work, if you want to convert a JSON string like { "id": 1, "name": "Some Guy", "email": "example1#example.com" } into one User object.
But a JSON string like yours
{
"0": {
"id": 1,
"name": "Some Guy",
"email": "example1#example.com"
},
...
}
is interpreted as an Array (or HashMap?!) of User objects.
Try the following using Array:
users = gson.fromJson(result, User[].class);
or (if GSON interprets it as a HashMap):
users = gson.fromJson(result, HashMap<String, User>.class);
The more elegant way using code from Collections example from the Gson user guide would be using Collection:
Type collectionType = new TypeToken<Collection<User>>(){}.getType();
Collection<User> users= gson.fromJson(result, collectionType);
In the "Collections limitations" part is written the following:
While deserializing, Collection must be of a specific generic type
I'm not sure, but that could mean, that you have to to set collectionType to use List and not Collection as specific type.
or (if GSON interprets it as a HashMap):
Type hashMapType = new TypeToken<HashMap<String, User>>(){}.getType();
HashMap<String, User> users= gson.fromJson(result, hashMapType);
Good luck =)
EDIT
My try with the last solution was successul:
public class User {
private String id, name, email;
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
public static void main(String[] args) {
String result = ""
+ "{\"0\": { \"id\": 1, \"name\": \"Some Guy\", \"email\": \"example1#example.com\"},"
+ "\"1\": { \"id\": 2, \"name\": \"Person Face\", \"email\": \"example2#example.com\"}"
+ "}";
Gson gson = new Gson();
Type hashMapType = new TypeToken<HashMap<String, User>>() {
}.getType();
HashMap<String, User> users = gson.fromJson(result, hashMapType);
for (String key : users.keySet()) {
printUser(users.get(key));
}
}
private static void printUser(User user) {
System.out.printf("%s %s %s\n", user.getId(), user.getName(),
user.getEmail());
}