How to use JSON with difficult objects - java

I have problem with dynamic JSON data. I don't know how to put it into my JAVA class. I need "routes" data. But i don't know what i should do with this ""2019-05-27": {...".
It is part of JSON file...
{
"2019-05-26": {
"lastUpdate": "2019-05-26 06:05:02",
"routes": [
{
"routeId": 107,
"agencyId": 18
},
{
"routeId": 222,
"agencyId": 22
}
]
},
"2019-05-27": {
"lastUpdate": "2019-05-27 06:05:02",
"routes": [
{
"routeId": 33,
"agencyId": 14
},
{
"routeId": 345,
"agencyId": 2232
}
]
}
}
The code below doesn't work. It is not Map<String,Map<String, String>>. I think it is -
Gson gson = new Gson();
Type mapType = new TypeToken<Map<String,Map<String, String>>>() {}.getType();
Map<String,Map<String, String>> map = null;
try {
map = gson.fromJson(new FileReader("routes.json"), mapType);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
What should I do to take this data ?

Create POJO classes like that :
public class MyObject {
private List<Route> routes;
private String lastUpdate;
public MyObject(List<Route> routes, String lastUpdate) {
this.routes = routes;
this.lastUpdate = lastUpdate;
}
// assume getters and setters
}
public class Route {
private String routeId;
private String agencyId;
public Route(String routeId, String agencyId) {
this.routeId = routeId;
this.agencyId = agencyId;
}
// assume getters and setters
}
To test it :
public static void main(String[] args) throws IOException {
Gson gson = new Gson();
String json = Files.lines(Paths.get("src/main/resources/data.json")).collect(Collectors.joining());
Type mapType = new TypeToken<Map<String, MyObject>>() {}.getType();
Map<String, MyObject> map = gson.fromJson(json, mapType);
map.forEach((s, myObject) -> System.out.println(s + " " + myObject.getLastUpdate()));
}
The output is :
2019-05-26 2019-05-26 06:05:02
2019-05-27 2019-05-27 06:05:02
You just need to create a map which has date as a key and custom object as value.

Please check this line :
json = Files.lines(Paths.get("routes.json")).collect(Collectors.joining());
this line may store null value and that's why you are getting a java.lang.NullPointerException.
Please check this by debugging. I think you will get the solution.

Related

How to use gson for getstring of json?

I am new to use gson.
I found a lots of tutorial there I can learn of gson but there are using recylerview and model file.
JsonObjectRequest request = new JsonObjectRequest(LoginUrl, new JSONObject(params),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d(TAG , String.valueOf(response));
try {
String statusObject = response.getString("status");
String msgObject = response.getString("msg");
if (statusObject.equals("200")) {
JSONArray jsonArray = response.getJSONArray("response");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject managerResponse= jsonArray.getJSONObject(i);
// userIdObject = managerResponse.getString("user_id");
// String nameObject = managerResponse.getString("name");
// String emailObject = managerResponse.getString("email");
// String mobileObject = managerResponse.getString("mobile");
// String postobject = managerResponse.getString("post");
// pojectObject = managerResponse.getString("project");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
}
Here I can get data from jsonrequest using volley but unable to do that same process using volley and gson. Is there any way to use gson?
Thank You.
Update
My JSON Response
{
"status": "200",
"msg": "Successfully",
"response": [
{
"user_id": "1",
"name": "HEMANT OJHA",
"email": "hemguna#gmail.com",
"mobile": "9584919991",
"address1": "C92, PALLAWI NAGAR BABADIYA KALAN",
"user": "admin",
"api_token": "admin"
}
]
}
Generating POJO class from JSON
// Considering your response consists of json objects & json array
// Create a POJO class for your response with the link above
{
"keyOne": 1,
"keyTwo": "Some Value",
"someArray": [{
"key": "Value"
},
{
"key": "Value"
}
]
}
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class ExampleClass {
#SerializedName("keyOne")
#Expose
private int keyOne;
#SerializedName("keyTwo")
#Expose
private String keyTwo;
#SerializedName("someArray")
#Expose
private List<SomeArray> someArray = null;
public int getKeyOne() {
return keyOne;
}
public void setKeyOne(int keyOne) {
this.keyOne = keyOne;
}
public String getKeyTwo() {
return keyTwo;
}
public void setKeyTwo(String keyTwo) {
this.keyTwo = keyTwo;
}
public List<SomeArray> getSomeArray() {
return someArray;
}
public void setSomeArray(List<SomeArray> someArray) {
this.someArray = someArray;
}
}
// Parsing JSON response with GSON
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
ExampleClass resultObj = gson.fromJson(jsonObject.toString(), ExampleClass.class);
int keyOneValue = resultObj.getKeyOne() // First JSON Object
// Getting String value
String keyTwoValue = resultObj.getKeyTwo() // Second JSON Object
List<SomeArray> yourJSONArray = resultObj.getSomeArray() // Getting JSON Array contents
// Depending on JSON response that you've updated in your question
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
ExampleClass resultObj = gson.fromJson(jsonObject.toString(),ExampleClass.class);
String status = resultObj.getStatus();
String msg = resultObj.getMsg();
List<Response> responseList = resultObj.getResponse();
The best way to use for entire app is create a Utils class and use it for conversion.
GsonUtils.java
// This Class is useful for mapping Json into Java Objects and vice versa.
public class GsonUtils {
private static final Gson gson = new Gson();
// This will Convert Java Objects into JSON String...
public static String toGson(Object object) {
return gson.toJson(object);
}
// Gives Java Objects from JSON
public static <T> T fromGson(String json, Class<T> type) {
return gson.fromJson(json, type);
}
public static JsonArray fromGson(String json) {
return new JsonParser().parse(json).getAsJsonArray();
}
}
Now convert any json to and from POJO via,
POJO pojoObj = GsonUtils.toGson(POJO.class);
Try this
JSON response
String str = new Gson().toJson(response)

how to get json from inside a json

I've the below json data.
{
"RestResponse" : {
"messages" : [ "More webservices are available at http://www.groupkt.com/post/f2129b88/services.htm", "Total [249] records found." ],
"result" : [ {
"name" : "Afghanistan",
"alpha2_code" : "AF",
"alpha3_code" : "AFG"
}, {
"name" : "Åland Islands",
"alpha2_code" : "AX",
"alpha3_code" : "ALA"
}, {
"name" : "Albania",
"alpha2_code" : "AL",
"alpha3_code" : "ALB"
}, {
"name" : "Algeria",
"alpha2_code" : "DZ",
"alpha3_code" : "DZA"
}]
}
}
Here I need to loop through the country names and print it in my console.
I'm trying the below code.
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map = mapper.readValue(text, new TypeReference<Map<String, Object>>() {
});
Map<String, Object> map1 = (Map<String, Object>) map.get("RestResponse");
Map<String, Object> map2 = (Map<String, Object>) map1.get("result");
System.out.println(map1);
When I run this I get exception as
Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.util.Map
at onlyJava.Countries.getTheCurrentWeather(Countries.java:45)
at onlyJava.Test.main(Test.java:6)
when I comment out Map<String, Object> map2 = (Map<String, Object>) map1.get("result");, it gives me the result starting from messages:.... till the end.
please let me know where am I going wrong and how can I fix this.
Updated code.
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map = mapper.readValue(text, new TypeReference<Map<String, Object>>() {
});
Map<String, Object> map1 = (Map<String, Object>) map.get("RestResponse");
List<Object> resultList = new ArrayList<Object>();
resultList = mapper.readValue(map1.get("result"), new TypeReference<List<Object>>() {
});
System.out.println(resultList);
Thanks
You are getting jsonObject. Value against key "RestResponse" is inside {} brackets that its again a json Object thats why you are able to map it to a Map. but the value against key "result" is inside [] brackets and that is a list not a json object so you can not assign it to a Map. You should create an Arraylist an assign it to that.
You are getting jsonObject. Value against key "RestResponse" inside "Result" is jsonArray below code for find country name from json.
test with Json Library : org.json
String jsonString = "{ \"RestResponse\" : { \"messages\" : [ \"More webservices are available at http://www.groupkt.com/post/f2129b88/services.htm\", \"Total [249] records found.\" ], \"result\" : [ { \"name\" : \"Afghanistan\", \"alpha2_code\" : \"AF\", \"alpha3_code\" : \"AFG\" }, { \"name\" : \"Åland Islands\", \"alpha2_code\" : \"AX\", \"alpha3_code\" : \"ALA\" }, { \"name\" : \"Albania\", \"alpha2_code\" : \"AL\", \"alpha3_code\" : \"ALB\" }, { \"name\" : \"Algeria\", \"alpha2_code\" : \"DZ\", \"alpha3_code\" : \"DZA\" }] } }";
JSONObject jObject = new JSONObject(jsonString);
JSONObject obj1 = jObject.getJSONObject("RestResponse");
JSONArray result = obj1.getJSONArray("result");
for (int i = 0; i < result.length(); i++) {
JSONObject company = result.getJSONObject(i);
String name = company.getString("name");
System.out.println("Country Name : "+name);
}
Output :
Country Name : Afghanistan
Country Name : Åland Islands
Country Name : Albania
Country Name : Algeria
Result is of type list, so in order to parse it properly you need to do something like below:
List<Object> resultList = new ArrayList<Object>();
resultList = JsonMapper.readValue(map1.get("result"), new TypeReference<List<Object>>(){});
Also, to simplify rather than parsing node one by one, you can create a POJO of result object and have json mapper do automatic conversion.
EDIT: In order to have proper mapping create a pojo of root and subsequent objects and parse it as per below:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
String jsonString = "{\"RestResponse\":{\"messages\":[\"More webservices are available at http://www.groupkt.com/post/f2129b88/services.htm\", \"Total [249] records found.\" ],\"result\":[{\"name\":\"Afghanistan\",\"alpha2_code\":\"AF\",\"alpha3_code\":\"AFG\"}, {\"name\":\"Åland Islands\",\"alpha2_code\":\"AX\",\"alpha3_code\":\"ALA\"}, {\"name\":\"Albania\",\"alpha2_code\":\"AL\",\"alpha3_code\":\"ALB\"}, {\"name\":\"Algeria\",\"alpha2_code\":\"DZ\",\"alpha3_code\":\"DZA\"}]}}";
Root response = null;
try {
response = mapper.readValue(jsonString, Root.class);
for (Result result : response.getRestResponse().getResult())
System.out.println("Country Name: " + result.getName());
} catch (IOException e) {
e.printStackTrace();
}
Root Class:
RestResponseNode RestResponse;
public RestResponseNode getRestResponse() {
return RestResponse;
}
public void setRestResponse(RestResponseNode restResponse) {
RestResponse = restResponse;
}
#Override
public String toString() {
return "Root [RestResponseNode=" + RestResponse + "]";
}
RestResponseNode Class:
List<String> messages;
List<Result> result;
public List<String> getMessages() {
return messages;
}
public void setMessages(List<String> messages) {
this.messages = messages;
}
public List<Result> getResult() {
return result;
}
public void setResult(List<Result> result) {
this.result = result;
}
#Override
public String toString() {
return "RestResponseNode [messages=" + messages + ", result=" + result + "]";
}
Result Class:
String name;
String alpha2_code;
String alpha3_code;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAlpha2_code() {
return alpha2_code;
}
public void setAlpha2_code(String alpha2_code) {
this.alpha2_code = alpha2_code;
}
public String getAlpha3_code() {
return alpha3_code;
}
public void setAlpha3_code(String alpha3_code) {
this.alpha3_code = alpha3_code;
}
#Override
public String toString() {
return "Result [name=" + name + ", alpha2_code=" + alpha2_code + ", alpha3_code=" + alpha3_code + "]";
}

How can I store key-value pairs in JSON to be deserialized in Java?

I have data in JSON like so:
{
"foo": "bar",
"key": true,
"otherKey": 10
}
The key is a String and the value is a primitive (int, float, double, long, etc.) or a String. I want a simple, cast-free wrapper for each of the above.
Here's my wrapper class:
public final class Wrapper<T> {
private String key;
private T value;
}
If I specified Wrapper[] wrappedValues in an object to be deserialized, could I (using Jackson or GSON) deserialize the map to a list of the wrapper?
Thanks for any replies!
First of all, the input you specified can never be deserialized into an array or collection because it isn't one. a json collection of pairs of key-value looks like this
[
{"foo": "bar"},
{"key": true},
{"otherKey": 10}
]
and it can be deserialized into a collection of Wrappers if you make the class like this
public class Wrapper<T> {
private String key;
private T value;
#JsonAnySetter
public void set(String key, Object value) {
this.key = key;
this.value = (T)value;
}
public String toString() { // just for nice printing
return key + "=" + value.toString();
}
}
and then you have to tell Jackson what is the generic type of the collection that will host the deserialized json:
public static void main(String[] args)
{
String str = "[ {\"foo\": \"bar\"}, {\"key\": true}, {\"otherKey\": 10} ]";
try (InputStream is = new ByteArrayInputStream(str.getBytes("UTF-8"))) {
ObjectMapper objectMapper = new ObjectMapper();
JavaType listWrappersType = objectMapper.getTypeFactory()
.constructCollectionType(List.class, Wrapper.class);
List<Wrapper> list = objectMapper.readValue(is, listWrappersType);
System.out.println(list);
} catch (Exception e) {
e.printStackTrace();
}
}
output:
[foo=bar, key=true, otherKey=10]
If you just want to load pairs of key-value and not worry about type of value, then with Jackson you can load it all into Map<String, ?>
public static void main(String[] args)
{
String str = "{ \"foo\": \"bar\", \"key\": true, \"otherKey\": 10 }";
try (InputStream is = new ByteArrayInputStream(str.getBytes("UTF-8"))) {
Map<String, ?> map = new ObjectMapper().readValue(is, Map.class);
// print map contents
System.out.println(map);
// print type of map values
System.out.print(entry.getKey() + "=" + entry.getValue().getClass()+ ", "));
System.out.println();
} catch (Exception e) {
e.printStackTrace();
}
}
output
{foo=bar, key=true, otherKey=10}
foo=class java.lang.String, key=class java.lang.Boolean, otherKey=class java.lang.Integer,

Recursive Method to create Json object

I like to know how I might do the following:
I want to create a json format of the following:
I want to be able to create a recursive function that takes an object holding a list of other objects of the same type and in a method to recursively create the format below.
{
"name": "lib",
"contains": [{
"name": "room",
"contains": [{
"name": "bookshelf",
"contains": [{
"name": "shelf",
"contains": []
}]
}]
}]
}
I have this as the following method:
private JSONObject json = new JSONObject();
public JSONObject setupLib(Contains contain) {
int count = contain.getContainerList().size();
for(int i = 0; i < count; i++){
try {
json.put("name", contain.getContainerList().get(i).getContainerName());
if(contain.getContainerList().size() != 0) {
Contains contains = (Contains) contain.getContainerList().get(i);
JSONArray array = new JSONArray();
json.put("contain",array.put(setupLib(contains)));}
}catch (JSONException e){
Log.i(Tag, e.getMessage());
}
}
return json;
}
I get a stackoverflow on the array/object
Two options
Do it yourself recursively
Use a library such as Gson to save you the development time and effort
Since this is a learning experience, I have shown both that return this JSON.
{
"name": "lib",
"contains": [{
"name": "room",
"contains": [{
"name": "bookshelf",
"contains": [{
"name": "shelf",
"contains": []
}]
}]
}]
}
public static void main(String[] args) {
Contains lib = new Contains("lib");
Contains room = new Contains("room");
Contains bookshelf = new Contains("bookshelf");
Contains shelf = new Contains("shelf");
bookshelf.add(shelf);
room.add(bookshelf);
lib.add(room);
// Option 1
System.out.println(setupLib(lib).toJSONString());
// Option 2
Gson gson = new Gson();
System.out.println(gson.toJson(lib));
}
private static JSONObject setupLib(Contains contain) {
if (contain == null) return null;
LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
JSONArray array = new JSONArray();
for (Contains c : contain.getContainerList()) {
JSONObject innerContain = setupLib(c);
if (innerContain != null) {
array.add(innerContain);
}
}
map.put("name", contain.getName());
map.put("contains", array);
return new JSONObject(map);
}
This is the model object, for reference
public class Contains {
#SerializedName("name")
#Expose
private String name;
#SerializedName("contains")
#Expose
private List<Contains> contains;
public Contains(String name) {
this.name = name;
contains = new ArrayList<Contains>();
}
public void setName(String name) {
this.name = name;
}
public void add(Contains c) {
this.contains.add(c);
}
public void setContainerList(List<Contains> contains) {
this.contains = contains;
}
public String getName() {
return name;
}
public List<Contains> getContainerList() {
return this.contains;
}
}
I think is far easier if you'd serialize both the JSONObject and Contains classes. This way you'll be able to use the Jackson library to create the JSON file for you.
You can find more information about the Jackson library on the following GitHub page: https://github.com/FasterXML/jackson.

Copy filtered JSON data from one file to another using gson library in java

I want to copy JSON fields from one file to another but only after the field satisfies a particular condition, as for example
{"dataset":
[
{"album_id":1,
"album_type":"Live Performance",
"artist_name":"John Doe",....
}
]
}
I want to copy only those records which have a user given artist_name or any other property, else skip the tuple for copying. I am using the following code to add the filtered records to a JSONObject "wr" which I then write to my output file. But its not giving me the desired results
public static void dumpJSONElement(JsonElement element) {
if (element.isJsonObject()) {
JsonObject obj = element.getAsJsonObject();
java.util.Set<java.util.Map.Entry<String,JsonElement>> entries = obj.entrySet();
java.util.Iterator<java.util.Map.Entry<String,JsonElement>> iter = entries.iterator();
while (iter.hasNext()) {
java.util.Map.Entry<String,JsonElement> entry = iter.next();
if(entry.getKey().equals(filterKey)){
if(! entry.getValue().toString().replace("\"", "").equals(filterValue)){
wr.put(entry.getKey(), entry.getValue());
}
}
else{
wr.put(entry.getKey(), entry.getValue());
}
dumpJSONElement(entry.getValue());
}
} else if (element.isJsonArray()) {
JsonArray array = element.getAsJsonArray();
java.util.Iterator<JsonElement> iter = array.iterator();
while (iter.hasNext()) {
JsonElement entry = iter.next();
dumpJSONElement(entry);
}
} else if (element.isJsonPrimitive()) {
JsonPrimitive value = element.getAsJsonPrimitive();
} else if (element.isJsonNull()) {
} else {
System.out.println("Error. Unknown type of element");
}
}
use code below code to convert your json string to generic java type List<Map<Object, Object>>, use code below.
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class Test {
public static void main(String... args) {
String str = "[{'id':1,'name':'yogesh'},{'id':2,'name':'aarush', 'degree': 'MCA'}]";
Type type = new TypeToken<List<Map<Object, Object>>>() {
}.getType();
List<Map<Object, Object>> list = new Gson().fromJson(str, type);
System.out.println(new Gson().toJson(list));
filterList(list, "name", "yogesh");
System.out.println(new Gson().toJson(list));
}
public static void filterList(List<Map<Object, Object>> list, String key, Object value) {
for (Map<Object, Object> map : list) {
if (map.containsKey(key)) {
if (map.get(key).equals(value)) {
list.remove(map);
}
}
}
}
}
here i filterd name=yogesh record.
output:
[{"id":1.0,"name":"yogesh"},{"id":2.0,"name":"aarush","degree":"MCA"}]
[{"id":2.0,"name":"aarush","degree":"MCA"}]
I had similar issues and I googled, read a lot about this. In conclusion, the best(most efficient) way (with gson) is to write a custom TypeAdapter for your case.
You can test sample code below (it is working as you expected):
public static void answer() {
String jsonAsText = "{\"dataset\":[{\"album_id\":1,\"album_type\":\"Live Performance\",\"artist_name\":\"John Doe\"},{\"album_id\":2,\"album_type\":\"A Dummy Performance\"}]}";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(List.class, new AlbumInfoListTypeAdapter());
Gson gson = gsonBuilder.create();
List<AlbumInfo> dataSet = gson.fromJson(jsonAsText, List.class);
System.out.println(gson.toJson(dataSet));
}
private static class AlbumInfo {
int album_id;
String album_type;
String artist_name;
}
private static class AlbumInfoListTypeAdapter extends
TypeAdapter<List<AlbumInfo>> {
#Override
public List<AlbumInfo> read(com.google.gson.stream.JsonReader in)
throws IOException {
List<AlbumInfo> dataSet = new ArrayList<AlbumInfo>();
in.beginObject();
while (in.hasNext()) {
if ("dataset".equals(in.nextName())) {
in.beginArray();
while (in.hasNext()) {
in.beginObject();
AlbumInfo albumInfo = new AlbumInfo();
while (in.hasNext()) {
String jsonTag = in.nextName();
if ("album_id".equals(jsonTag)) {
albumInfo.album_id = in.nextInt();
} else if ("album_type".equals(jsonTag)) {
albumInfo.album_type = in.nextString();
} else if ("artist_name".equals(jsonTag)) {
albumInfo.artist_name = in.nextString();
}
}
in.endObject();
if (albumInfo.artist_name != null && !"".equals(albumInfo.artist_name.trim())) {
dataSet.add(albumInfo);
} else {
System.out.println("Album info ignored because it has no artist_name value");
}
}
in.endArray();
}
}
in.endObject();
return dataSet;
}
#Override
public void write(com.google.gson.stream.JsonWriter out,
List<AlbumInfo> dataSet) throws IOException {
out.beginObject();
out.name("dataset").beginArray();
for (final AlbumInfo albumInfo : dataSet) {
out.beginObject();
out.name("album_id").value(albumInfo.album_id);
out.name("album_type").value(albumInfo.album_type);
out.name("artist_name").value(albumInfo.artist_name);
out.endObject();
}
out.endArray();
out.endObject();
}
}
You can modify the read and the write methods. Gson has many cool functions. I strongly suggest you to read samples at this link.
Edit:
Incoming json text:
{
"dataset": [
{
"album_id": 1,
"album_type": "Live Performance",
"artist_name": "John Doe"
},
{
"album_id": 2,
"album_type": "A Dummy Performance"
}
]
}
The output at System.out.println at answer method:
[
{
"artist_name": "John Doe",
"album_type": "Live Performance",
"album_id": 1
}
]

Categories