I want to get the value of the key "FullName" from this json response:
{
"Succeeded": true,
"DebugError": "",
"SystemUser": {
"ID": 94,
"FullName": "John Smith",
"Email": "abcd#gmail.com",
"PhoneNumber": "0000000000",
"Country": "USA"
}
}
Inside the onResponse method I did this:
// code..
#Override
public void onResponse(JSONObject response) {
Gson gson = new Gson();
JsonReader reader = new JsonReader(new StringReader(response.getJSONObject("SystemUser").get("FullName").toString()));
reader.setLenient(true);
String name = gson.fromJson(reader, String.class);
Log.i( " name: ", name + "");
// I tried to use getString("FullName") but shows the same result.
}
// code..
The value in Logcat is => name: John
Why didn't print the full name (John Smith) ??
Seems like your GSON implementation is redundant. Just use
response.getJSONObject("SystemUser").getString("FullName")
Rather than proceeding this way you can go for a better approach. Most of the apps have complex json structures, for which this kinda approach is not advisable.
Create a model class by copy pasting your sample json to jsonschema2pojo. Now select Target language:Java , Annotation style: Gson
Download or copy paste the generated model class and use the following (Assuming your class name as UserDetails).
UserDetails userDetails = gson.fromJson(response.toString(), UserDetails.class);
Now you have the model class populated with all the values. Retrieve which ever you want.
NOTE: Variable names and inner class names should be exactly same as the JSON structure. Better use annotation. Or else the model class will not get populated correctly
Related
If an "action" key-value pair is repeated, I want to append each associated "myObject" to a list as shown below. Is there a way to achieve this using GSON or JACKSON? Unfortunately, there is no option to edit the input JSON. If the ask is not clear, please let me know.
Input
[
{
myObject: {
name: "foo",
description: "bar"
},
action: "create",
},
{
myObject: {
name: "baz",
description: "qux"
},
action: "create",
},
];
Required Output
{
"action": "create",
"myObject": [
{
name: "foo",
description: "bar"
},
{
name: "baz",
description: "qux"
},
]
};
I am new to JSON parsing in Java and unfortunately haven't found a use case like mine on StackOverflow. I have tried configuring my ObjectMapper like so -
new ObjectMapper().configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
and using
#JsonAnySetter
annotation, but haven't gotten them to work yet.
You could solve this with two separate model classes, one for the original structure and one for the transformed one. For simplicity I call them OriginalModel and TransformedModel below, you should probably pick more meaningful names. The following code uses Gson but you can probably achieve something similar with Jackson as well.
class OriginalModel {
String action;
MyObjectData myObject;
}
class TransformedModel {
String action;
List<MyObjectData> myObject;
public TransformedModel(String action, List<MyObjectData> myObject) {
this.action = action;
this.myObject = myObject;
}
}
class MyObjectData {
String name;
String description;
}
If you declare these classes as nested classes you should make them static.
Then you can first parse the JSON data with the original model class, manually create the desired result structure using the transformed class and serialize that to JSON:
Gson gson = new Gson();
List<OriginalModel> originalData = gson.fromJson(json, new TypeToken<List<OriginalModel>>() {});
// Group MyObjectData objects by action name
// Uses LinkedHashMap to preserve order
Map<String, List<MyObjectData>> actionsMap = new LinkedHashMap<>();
for (OriginalModel model : originalData) {
actionsMap.computeIfAbsent(model.action, k -> new ArrayList<>())
.add(model.myObject);
}
List<TransformedModel> transformedData = new ArrayList<>();
for (Map.Entry<String, List<MyObjectData>> entry : actionsMap.entrySet()) {
transformedData.add(new TransformedModel(entry.getKey(), entry.getValue()));
}
String transformedJson = gson.toJson(transformedData);
I am using custom serialization/deserialization in GSON. for that i have custom gsonAdapter. i am using custom because of difference in property names.
My class :
public class Emp {
String name;
String age;
}
and my json payload :
{
"xyz/abc/name": "abc",
"xyz/abc/age": "10"
}
now i am having problem while converting my list of json to class.
[{
"xyz/abc/name": "abc",
"xyz/abc/age": "10"
},
{
"xyz/abc/name": "xyz",
"xyz/abc/age": "20"
}]
tried using
Type listType = new TypeToken<ArrayList<Emp>>(){}.getType();
List<Emp> yourClassList = new Gson().fromJson(jsonArray, listType)
but it returns Emp object with all fields initialized as null.
so not able to figure out what else i need to do, if anyone can throw light on the parts i am missing.
I am trying to map the following response:
{
"data": {
"id": "1574083",
"username": "snoopdogg",
"full_name": "Snoop Dogg",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1574083_75sq_1295469061.jpg",
"bio": "This is my bio",
"website": "http://snoopdogg.com",
"counts": {
"media": 1320,
"follows": 420,
"followed_by": 3410
}
}
into an object where I only want to retrieve the username, full_name, and id fields.
Ex: something like:
public class User{
String id;
String username;
String full_name;
// getters + setters
}
Is there a way of doing this without first having to store the data object into a Map?
Use Jackson API. It should be simple:
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(jsonString, User.class); //jsonString is your actual json string.
You might want to tweak your User class to match the JSON string. E.g. your user class needs to have a 'data' field as List<Data> data; where 'Data' is another POJO. You can add the "id", "userName", etc fields in the 'Data' pojo.
You can either do it by hand via, for example, regexp or utilize any of JSON libraries like Jackson, GSON etc.
With GSON it's pretty simple. Say your json is stored in a String jsonString variable.
Gson gson = new Gson();
YourObject = gson.fromJson(jsonString, YourObject.class);
Although I'm not sure what will happen, since your jsonString doesn't have a key called User. However, this should work if you first extract data from your jsonString and name your POJO Data.
My program has to output following JSON format:
{ "success": {
"code": 1,
"desc": "success" },
"response": {
"res1": [
{
"Item": "item1",
"Description": [
{
"desc": "ad1",
"active": true,
"details": [
{
"Type": "Type1",
"Count": 2,
"Status": true
},
{
"Type": "TYpe2",
"Count": 3,
"Status": false
},
]
},
{
"desc": "item2",
"active": true,
"details": [
{
"Type": "Type1",
"Count": 4,
"Active": true
}
]
},
{
"Item": "item2",
"Description": [
{
"desc": "d2",
"Active": true,
"details": [
{
"Type": "Type3",
"Count": 6,
"Active": true
},
]
},
]
}
]
}
}
I have wrote following to create this json format
HashMap<String, HashMap<String, String>> m1 = new HashMap<String, HashMap<String, String>>();
HashMap<String, String> m2 = new HashMap<String, String>();
HashMap<String, ArrayList<HashMap<String, String>>> m3 = new HashMap<String, ArrayList<HashMap<String, String>>>();
For creating the mentined JSON format, I tried to put m3 and m2 in m1. But since these are not with same type, it won't allow to put.
I am using GSON to convert the collection to JSON.
Gson gson = new Gson();
String json1 = gson.toJson(m1);
My Question is: For creating that JSON format, which collection in Java I have to use?
The best way to deal with a complex JSON structure like that is to create a class with the same structure with properties that represent the underlying arrays as lists. Then, you can use gson to convert the object(s) to JSON in a straightforward way.
In other words, instead of trying to fit the structure into a combination of complex collections or existing Java classes, create a class that is an exact representation of the data, populate it, and then convert it to JSON.
Why don't you let the code generated for you?
After the pojos are created you can of course change the code to tailor your needs.
Create a ResponseWrapper class and build your json accordingly.
Sample code:
public class ResponseWrapper<T>{
private Map<String, T> wrappedObjects = new HashMap<String, T>();
public ResponseWrapper() {
}
public ResponseWrapper(String name, T wrappedObject) {
this.wrappedObjects.put(name, wrappedObject);
}
..
..
Your json can be built like this:
ResponseWrapper response = new ResponseWrapper<ResponseWrapper>();
Items[] item = ....
//item can itself have Description, etc.
response.set("res1", (ArrayList) items);
Thanks for notepad++ and its json view plugin, i can read your json data in proper format. (although your data missing a few brackets)
In my oponion, json structure can be converted into Map but i personally don't like that idea much.
The other way to do is using Java POJO to define your JSON object and then convert it to json. Excellent example here
OK. We will check your data and create Java POJO for it. It's simple and should be something like this
public class YourJsonObj {
public SuccessObj success;
public ResponseObj response;
}
where SuccessObj and ResponseObj are another structure Classes like this:
public class SuccessObj {
public Integer code;
public String desc;
}
public class ResponseObj {
public List<ResObj> res1;
}
Another sub class appear: ResObj. All you have to do is continue define it:
public class ResObj {
public String Item; // << this property's name does't make java happy
public List<DescriptionObj> Description // << this property's name does't make java happy
}
Continue to do this definition till the end of your data. And you got it.
My suggestion is to replicate the same hierarchy of the fields in your JSON example.
By the Google Gson library you can convert (in 2 lines of code) your Java object to a JSON object. Please check the following example (from the user guide of the relative project).
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
// no-args constructor
}
}
// Serialization
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);
// ==> json is {"value1":1,"value2":"abc"}
I'm using retrofit2 to handle http request after calling from API. Let me explain this.
I have 2 java class(POJO) created to handle user and lecturer data which is User.java and Lecturer.java respectively. For the response data such as :
{
"users": [
{
"user_id": "28",
"user_email": "john#abc.com",
"user_password": "123"
}
]
}
i can use User.java class to handle this response. Nothing complex in this file, only contains getter and setter method. Same goes to lecturer data, here is the example of lecturer data :
{
"lecturers": [
{
"lecturer_id": "3",
"user_id": "28",
"lecturer_name": "johny2"
}
]
}
i can handle it by using Lecturer.java class.
But the problem is, if the response contains both user and lecturer data on a single json, how to handle it?? . Here is the example of request :
{
"users": [
{
"user_id": "28",
"user_email": "john#abc.com",
"user_password": "123",
"lecturer_id": "3",
"lecturer_name": "johny2"
}
]
}
To solve this problem, i think i need to create another java class that contains both User and Lecturer class on it, unfortunately at here i'm stuck.
This is new file, that i tried to create (Userlecturer.java) :
public class UserLecturer {
User user;
Lecturer lecturer;
// how to implement on this part
}
Here is UserLecturer interface :
public interface UserLecturerInterface {
#GET ( "api/endpoint/here" )
Call<UserLecturer> getLecturerByUserId (#Path( "userId" ) String userId );
}
Appreciated for any helps. Ask me for more inputs if above use case did't clear enough. Thanks
I think the POJO should be:
public class Users {
String userId;
String userEmail;
String userPassword;
String lecturerId;
String lecturerName;
}
Even though there are 2 models inside the JSON, you only need 1 model for Retrofit.
If you really want to split the 1 JSON response into 2 models, I think you have to implement custom JSON converter.
Gson gson = new GsonBuilder()
.registerTypeAdapter(UserLecture.class, new JsonDeserializer<UserLecture>() {
public UserLecture deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonArray usersJsonArray = json.getAsJsonObject().getAsJsonArray("users");
JsonObject userJsonObject = usersJsonArray.getAsJsonArray().get(0).getAsJsonObject();
User user = new User();
user.setUserId(userJsonObject.get("user_id").getAsString());
user.setUserEmail(userJsonObject.get("user_email").getAsString());
user.setUserPassword(userJsonObject.get("user_password").getAsString());
Lecturer lecturer = new Lecturer();
lecturer.setLecturerId(userJsonObject.get("lecturer_id").getAsString());
lecturer.setLecturerName(userJsonObject.get("lecturer_name").getAsString());
return new UserLecture(lecturer, user);
}
})
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl([YOUR_BASE_URL])
.addConverterFactory(GsonFactoryConverter.create(gson))
.build();
This is some code I use to convert longs to Java Date objects.
Presumably, you can do the same thing for your UserLecture object. You should be able to extract the individual json objects for User and Lecture, create a new UserLecture object and let User and Lecture as objects in it.
Gson gson = new GsonBuilder().registerTypeAdapter(UserLecture.class, new JsonDeserializer<UserLecture>() {
public UserLecture deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject user = json.getAsJsonObject().getAsJsonObject("user");
JsonObject lecture = json.getAsJsonObject().getAsJsonObject("lecture");
return new UserLecture(user, lecture);
}
}).create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonFactoryConverter.create(gson))
.build();
Then inside UserLecture:
public UserLecture(JsonObject userJson, JsonObject lectureJson) {
this.user = new User();
this.user.setUserId(userJson.get("user_id").getAsInt());
this.user.serUserEmail(userJson.get("user_email").getAsString());
//so on.
}
At first let me say that the JSON you need to process here is broken by design so you should urge the guy / department / company to fix it.
Secondly, JSON processors like Jackson allow to parse polymorphic data structures like this easily, but they require some kind of type flag to distinguish one of another type (i.e. type: "user" and type: "lecturer"). There is also a way to do this without such type flags, but there is a lot more hand work involved. The last example here shows how to do it.
Yes, it is one possible solution. Gson ignores all fields, which names doesnt match #SerializedName annotation. So, you may try another solution without creating any more pojo classes- return result as String, and try to parse this string as both classes. If one result is empty- then you have another. But, if both kbjects isnt empty- then original response contain fields from both pojos