how to get data from JSON file dynamically - java

So i made this mini app in purpose of learning JSON
so basically this is the JSON file
{
"Student1" : {
"name" : "Amine" ,
"mark": 19,
"Groupe": "G25"
},
"Student2" : {
"name" : "Zaki" ,
"mark": 19,
"groupe": "G25",
}
}
i tried instead of Putting "Student1" i thought i could do something like "Student"+"1"
private void parseJson(String toString) {
TextView showView = new TextView(this);
theLayout.addView(showView);
StringBuilder builder = new StringBuilder();
try {
JSONObject root = new JSONObject(toString);
/////// Here i got the INPUT string from an EditText
///// i think i should use some thing like .equals()
String theWantedStudent = "Student"+INPUT ;
JSONObject student = root.getJSONObject(theWantedStudent);
builder.append("Name : ")
.append(student.getString("name")).append("\n");
builder.append("Groupe : ")
.append(student.getString("groupe")).append("\n");
builder.append("Mark : ")
.append(student.getInt("mark")).append("\n");
} catch (JSONException e) {
e.printStackTrace();
}
showView.setText(builder.toString());
}
if there is a simpler methode let me know
thanks

I think what you want is a list of student ojects:
[
{
"name" : "Amine" ,
"mark": 19,
"groupe": "G25"
},
{
"name" : "Zaki" ,
"mark": 19,
"groupe": "G25"
}
]
Then use a class such as:
public class Student {
#JsonProperty("name")
private String name;
#JsonProperty("mark")
private Integer mark;
#JsonProperty("groupe")
private String groupe;
//getters and setters
}
Then use jackson to iterate thru the list

I recommend to use Gson to parse the JSON into an object.
After that, it will be easier to manipulate the data.
First, create a Java class with yout JSON structure:
public class Student {
private String name;
private int mark;
private String group;
// add the getters and setters
}
Then, use Gson to parse to the object:
Student student = new Gson().fromJson(json, Student.class);
If you want to build a JSON from an object use the Gson's method toJson:
Student student = new Student();
student.setName("Peter");
student.setMark(10);
student.setGroup("ABC");
String json = new Gson().toJson(student);
If you wanna more information about Gson check this tutorial, it's really good: https://mkyong.com/java/how-to-parse-json-with-gson/

Related

How to convert JSON to Java object if I do not know all json fields before parsing?

My service can receive several different jsons, such as:
{
"event":"conversation_started",
"context":"context information",
"user":{
"id":"01234567890A=",
"name":"John McClane",
"avatar":"http://avatar.example.com",
"country":"UK",
"language":"en",
"api_version":1
},
"subscribed":false
}
or
{
"event":"message",
"message":{
"type":"text",
"text":"a message to the service",
"location":{
"lat":12.34,
"lon":12.34
}
}
}
or several else jsons. The only field that is the same for all jsons is "event". All other fields can be different (depends on "event" value).
So the question is: how to convert those jsons to java objects (without making messy code)? The only way I know is to manually check "event" value (like json.startsWith("{\n\"event\":\"message\"") but I'm sure that there is any simple decision for doing this.
There are three ways I've done this. The first is to do what you're suggesting - parse the JSON, check the type, and create the object. Be very careful with using a String parser as you may or may not have things like new lines. Instead, do something like:
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(eventString);
String eventType = jsonNode.get("event").asText();
if( eventType.equalsIgnoreCase("conversation_started")) {
// create ConversationStarted object using something like:
ConversationStarted conversationStarted = objectMapper.readValue( eventString, ConversationStarted.class );
}
This, of course, requires all classes to have a concrete POJO to allow for deserialization.
Another way is to do what many other programming languages do and have a key/value map. There are a few ways to do this. One is with the Jackson libraries:
Map<String, Object> map = objectMapper.readValue(eventString, new TypeReference<Map<String,Object>>(){});
Map<String, Object> user = (Map<String, Object>) map.get("user");
System.out.println( "conversation started - avatar is " + user.get("avatar"));
That way you can pass around the Map and extract as needed. Note that you still need to understand the structure of the JSON but you don't need to have a POJO for it.
Lastly is a variation on the second solution. Using JSONPath you can pull out what you need directly. Again you will want to first check out which type of event you have. Something like:
if( JsonPath.read(eventString, "$.event").equals("conversation_started") ) {
String avatar = JsonPath.read(eventString, "$.user.avatar");
System.out.println("conversation started - avatar is " + avatar);
}
The last two methods require you to pull out values one at a time as shown. The first solution gives you a full object to work with. It is your call as to what works best in your environment.
UPD: If you don't want to convert JSON String to JAVA Object via declaring a POJO, you can parse it to JSONObject(com.alibaba.fastjson.JSONObject)
public class Event {
public static void main(String[] args) {
String jsonA = "{\"event\":\"conversation_started\",\"context\":\"context information\",\"user\":{\"id\":\"01234567890A=\",\"name\":\"John McClane\",\"avatar\":\"http://avatar.example.com\",\"country\":\"UK\",\"language\":\"en\",\"api_version\":1},\"subscribed\":false}";
String jsonB = "{\"event\":\"message\",\"message\":{\"type\":\"text\",\"text\":\"a message to the service\",\"location\":{\"lat\":12.34,\"lon\":12.34}}}";
JSONObject jsonObject = JSONObject.parseObject(jsonA);
String event = jsonObject.getString("event");
if (event.equals("message")) {
//do what you want to do
System.out.println("message event......");
} else if ("conversation_started".equals(event)) {
System.out.println("context information event......");
}
}
}
Declaring a class of Event as below, and then convert JSON String to a Event JAVA object.
#Data
public class Event {
private String event;
private String context;
private User user;
private boolean subscribed;
private Message message;
#Data
public static class User {
private String id;
private String name;
private String avatar;
private String country;
private String language;
private int api_version;
}
#Data
public static class Message {
private String type;
private String text;
private Location location;
#Data
public static class Location {
private double lat;
private double lon;
}
}
public static void main(String[] args) {
String jsonA = "{\"event\":\"conversation_started\",\"context\":\"context information\",\"user\":{\"id\":\"01234567890A=\",\"name\":\"John McClane\",\"avatar\":\"http://avatar.example.com\",\"country\":\"UK\",\"language\":\"en\",\"api_version\":1},\"subscribed\":false}";
String jsonB = "{\"event\":\"message\",\"message\":{\"type\":\"text\",\"text\":\"a message to the service\",\"location\":{\"lat\":12.34,\"lon\":12.34}}}";
ObjectMapper objectMapper = new ObjectMapper();
try {
Event eventA = objectMapper.readValue(jsonA, new TypeReference<Event>() {
});
System.out.println(objectMapper.writeValueAsString(eventA));
Event eventB = objectMapper.readValue(jsonB, new TypeReference<Event>() {
});
System.out.println(objectMapper.writeValueAsString(eventB));
} catch (IOException e) {
e.printStackTrace();
}
}
}
Use a JSON object. This is dynamic and can load any json. Then you can reference the event field consistently
Example 1
//import java.util.ArrayList;
//import org.bson.Document;
Document root = Document.parse("{ \"event\" : \"conversation_started\", \"context\" : \"context information\", \"user\" : { \"id\" : \"01234567890A=\", \"name\" : \"John McClane\", \"avatar\" : \"http://avatar.example.com\", \"country\" : \"UK\", \"language\" : \"en\", \"api_version\" : 1 }, \"subscribed\" : false }");
System.out.println(((String)root.get("event")));
Example 2
//import java.util.ArrayList;
//import org.bson.Document;
Document root = Document.parse("{ \"event\" : \"message\", \"message\" : { \"type\" : \"text\", \"text\" : \"a message to the service\", \"location\" : { \"lat\" : 12.34, \"lon\" : 12.34 } } }");
System.out.println(((String)root.get("event")));

I want to extract a value from a json

I want to extract a key and its value from json object. I am having a 3 objects in a json with parent child relation, named as
1. Parent,
2. childOne_OfParent and
3. child_OF_childOne.
I want to extract all the value of "userQueryId" from child_OF_childOne and store into a string type variable.
How do I perform this. Thanks in advance.
My Json object is:
{
"createdBy": "****",
"dashboardId": 1,
"childOne_OfParent": [
{
"createdBy": null,
"dashboardSectionId": 1,
"child_OF_childOne": [
{
"createdBy": "XYZ",
"userQueryId": "283"
},
{
"createdBy": "ABC",
"userQueryId": "284"
},
{
"createdBy": "AWS",
"userQueryId": "285"
}
]
}
]
}
You can use the json to create a model java class like this. I used your json to create the class using the site https://codebeautify.org/json-to-java-converter. You can give a classname of your choice in the Class_Name.
public class Class_Name {
private String createdBy;
private float dashboardId;
ArrayList < Object > childOne_OfParent = new ArrayList < Object > ();
// Getter Methods
public String getCreatedBy() {
return createdBy;
}
public float getDashboardId() {
return dashboardId;
}
// Setter Methods
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public void setDashboardId(float dashboardId) {
this.dashboardId = dashboardId;
}
}
Then you can use the Jackson to convert your json into a java object and access the data you want. Here jsonString is your json and the objResp is your object.
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Class_Name objResp = mapper.readerFor(Class_Name.class).readValue(jsonString);
Here is a useful guide for that. https://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/
The tool for these kind of tasks is JsonPath. It has xpath-like search capabilities.
Here is a working example of the given question
public static void main(String[] args) {
String searchQueryIds = "$.childOne_OfParent[*].child_OF_childOne[*].userQueryId";
try (InputStream is = Files.newInputStream(Paths.get("c:/temp/test.json"))) {
List<String> ids = JsonPath.parse(is).read(searchQueryIds);
System.out.println(ids);
} catch (Exception e) {
e.printStackTrace();
}
}
Assuming there is pojo for json and jackson library available. It will return comma separated queryUserIds.
Parent parent = new ObjectMapper().reader(Parent.class).readValue(inputJson);
String userIds = parent.getChildOne_OfParent().get(0).getChild_OF_childOne().stream()
.map(c -> c.getuserQueryId())
.collect(Collectors.joining(","));

Splitting a nested json to smaller jsons using Gson

I want to get a part of list json from a whole nested one. I have a json that looks like following:
{
"response": 200,
"responseMsg": "Allright",
"location": [
{
"stateId": 1,
"stateName": "West Bengal",
"district": [
{
"districtId": 15,
"districtName": "abc",
"village": [
{
"villageId": 121,
"villageName": "ABC"
},
{
"villageId": 90,
"villageName": "XYZ"
}
]
},
{
"districtId": 11,
"districtName": "xyz",
"village": [
{
"villageId": 58,
"villageName": "PQR"
}
]
}
]
}
]
}
I have written the bean files as following :
Details.java:
public class Details {
private int response = 0;
private String responseMsg = null;
private List<State> states = null;
public List<State> getLocation() {
return location;
}
State.java:
public class State {
private int stateId = 0;
private String stateName=null;
private List<District> district;
public List<District> getDistrict() {
return district;
}
Now, I want only the State json differently so that I can then use use it as List to populate the spinner in android.
For parsing the json, I am using
Gson googleJson = builder.create();Details details = googleJson.fromJson(result, Details.class);
List<State> stateList = details.getLocation();
But when i again convert this to json using gson.toJson(stateList) this gives:
[
{
"district": [
{
"village": [
{
"villageName": "Mekhliganj",
"villageId": 57
}
],
"districtName": "Cooch Bihar",
"districtId": 10
}
],"stateName=West Bengal","stateId":1
}
}
But this is other way round as state name goes in end when i again convert it to json.
Also , this same json (stateList) gives null pointer exception when I again try to parse it as:
State stateObj = gson.fromJson(stateList,State.class);
What should be the correct way to do this ? i.e. get a part of json (list) from a whole using gson and parse that part ?
Got the solution for you...
You are not passing the whole response in below function
try this steps to get whole response :
1) Store the data in String or any object class you are storing.
2)
Gson gson = new Gson();
String string = gson.toJson(response);
Note : You are just parsing remaining response. You are not parsing the original response. Just recheck the response when you parse in above function by putting break point on it.
public class Details {
private int response = 0;
private String responseMsg = null;
private Location location = null;
//add getter and setter
}
public class Location{
private List<State>stateList;
//add getter and setter
}
Finally
public class State {
private int stateId = 0;
private String stateName=null;
private List<District> district;
//add getter and setter
}

How to convert Json String with dynamic fields to Object?

I have the followed snipets of Json String:
{
"networks": {
"tech11": {
"id": "1",
"name": "IDEN"
},
"tech12": {
"id": "2",
"name": "EVDO_B"
}
}
}
I use some methods to convert this String to Object:
private static Gson mGson = new Gson();
...
public static WebObjectResponse convertJsonToObject(String jsonString) {
WebObjectResponse webObjectResponse = null;
if(jsonString != null && jsonString.length() > 1){
webObjectResponse = mGson.fromJson(jsonString, WebObjectResponse.class);
}
return webObjectResponse;
}
Where WebObjectResponse is class that should represent above mentioned String.
Its not complicated if I get static fields.
But in my case the values have different names: tech11, tech12 ....
I can use #SerializedName but its works in specific cases like convert "class" to "class_".
As you see networks Object defined as list of tech Objects but with different post-fix.
public class WebObjectResponse{
private DataInfoList networks = null;
}
This is static implementation, i defined 2 values tech11 and tech12 but next response might be techXX
public class DataInfoList {
private DataInfo tech11 = null;
private DataInfo tech12 = null;
}
public class DataInfo {
private String id = null;
private String name = null;
}
What is the good way to convert current Json String to Object where list of elements are Objects too and have different names?
Thank you.
Use a Map!
I would do the following
public class WebObjectResponse {
private Map<String, DataInfo> networks;
}
public class DataInfo {
private String id = null;
private String name = null;
}
// later
Gson gson = new Gson();
String json = "{\"networks\": {\"tech11\": { \"id\": \"1\",\"name\": \"IDEN\" }, \"tech12\": { \"id\": \"2\", \"name\": \"EVDO_B\" } }}";
WebObjectResponse response = gson.fromJson(json, WebObjectResponse .class);
For each object in json networks, a new entry will be added to the Map field of your class WebObjectResponse. You then reference them by techXX or iterate through the keyset.
Assuming a structure like this
{
"networks": {
"tech11": {
"id": "1",
"name": "IDEN"
},
"tech12": {
"id": "2",
"name": "EVDO_B"
},
"tech13": {
"id": "3",
"name": "WOHOO"
}, ...
}
}
We would need your class structure for more details.
As far as I am aware, I think you will need to have some mappings defined somewhere (I used xml's) and then try to match json with one of the mappings to create objects.
Google gson is good. I did it in Jackson
Also, converting objects should be trivial. But since you might have variable fields like tech11 and tech12 , you might want to store the "network" value as a string and then extract fields out of it when required.
Hope I could help.
Edit : Sotirious nails it.
Please use this link for converting SON Response to Java POJO class
http://www.jsonschema2pojo.org/

How to parse Complex json response in Android

I am trying to parse a JSON response. I am getting JSON response like below:
"libraryLastModified" : "2012-10-10 03:57:26",
"playlists" : { "10063" : { "id" : "10063",
"name" : "Favorites",
"songs" : [ "10006134",
"10006053",
"10006274",
"10006167",
]
},
"10157" : { "id" : "10157",
"name" : "80s",
"songs" : [ "10006694",
"10006695",
"10006697",
"10006699",
"10006698",
]
}
How can I access the id & name values?
I love GSON. In this scenario you'd create two classes.
public class PLayList {
private int id;
private String name;
private List<Integer> songs;
//getters and setters
}
public class Library {
private Date libraryLastModified;
private List<Playlist> playlists;
//getters and setters
}
Then you can write
Gson gson = new Gson();
Library result = gson.fromJson(theInput, Library.class);
Since the playlists is coming to you as key:value you'd need to write a custom deserializer for them. Taje a look at GSON deserializing key-value to custom object for how to do that
In pseudocode. I don't remember exactly the JSON methods
JSONObject mainObj = parseJson
JSONObject playLists = mainObj.getJSONObject("playlists")
JSONObject myList = playList.getJSONObject("10063")
id = myList.getString("id")
To iterate over several lists, you'd better transform playlists to a JSONArray, then you can iterate over it. If you can't do that, check the Android JSON API and check how to get all keys for a JSONObject and then iterate over the keys
for(int i=0;i<playlistKeys.length;i++){
playlistObj = playLists.getJSONObject(playlistsKey[i])
}
use google Gson.
http://code.google.com/p/google-gson/
class Response{
Date libraryLastModified;
Playlist []playlists;
class Playlist{
Long id;
String name;
Long[] songs;
}
}
String _response=... //Your response from web
Response response = new GsonBuilder().setDateFormat("yyyy-MM-dd' 'HH:mm:ss").create().fromJson(_response, Response.class);
String songName = response.playlists[0].name;

Categories

Resources