how to get json from inside a json - java

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 + "]";
}

Related

Return response from API as inner JSON objects

I use this code to get a list of countries as full name and ISO code:
public Map<String, Object> getCountryNameCodeList() {
String[] countryCodes = Locale.getISOCountries();
Map<String, Object> list = new HashMap<>();
for (String countryCode : countryCodes) {
Locale obj = new Locale("", countryCode);
list.put(obj.getDisplayCountry().toString(), obj.getCountry());
}
return list;
}
Rest API:
#GetMapping("shipping_countries")
public ResponseEntity<Map<String, Object>> getShippingCountries() {
return new ResponseEntity<Map<String, Object>>(countriesService.getCountryNameCodeList(), HttpStatus.OK);
}
I get the response data in this format:
{
"Papua New Guinea": "PG",
"Cambodia": "KH",
"Kazakhstan": "KZ",
"Paraguay": "PY",
.....
}
I would like to get the data this way:
[
{
name: "Papua New Guinea",
value: "PG"
},
{
name: "Unites States",
value: "US"
},
....
]
How I can modify the Java code to return the data this way?
Try this approach. You need to use data transfer object to return customized data.
Create a class DTO.
public class DTO {
private String key;
private String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
public String toString() {
return "DTO [key=" + key + ", value=" + value + "]";
}
}
Create Rest API in the controller. Example :
#RestController
public class Sample {
#RequestMapping("shipping_countries")
public ResponseEntity<List<DTO>> getShippingCountries() {
Map<String, String> map = new HashMap<>();
map.put("Papua New Guinea", "PG");
map.put("Cambodia", "KH");
List<DTO> list = getCustomisedData(map);
return ResponseEntity.ok(list);
}
private List<DTO> getCustomisedData(Map<String, String> map) {
List<DTO> dtos = new ArrayList();
for(Entry<String, String> value: map.entrySet()) {
DTO dto = new DTO();
dto.setKey(value.getKey());
dto.setValue(value.getValue());
dtos.add(dto);
}
return dtos;
}
}
Output :
The response you are getting is the JSON representation of a map, which is what you return.
The json you want is an array of objects, so if you want to return that- the easiest way will be to return it like that, is to return the set of Map.Entry from your map. Something like that:
#GetMapping("shipping_countries")
public ResponseEntity<Set<Map.Entry<String, Object>>> getShippingCountries() {
return new ResponseEntity<>(countriesService.getCountryNameCodeList().entrySet(), HttpStatus.OK);
}
Other way can be to create a Json serializer for the response, but it seems like an overkill

How to use JSON with difficult objects

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.

Setting an object class and then getting from it in the same method, looping through JSON and getting by value instead of key

Basically I am trying to loop through a JSONArray and based on the value of one of the keys in one of the objects I am trying to get the value of another key in the same object.
More specifically, I have a value that I want to pass in to a method, and in that method I want to loop through a JSONArray, and when the loop finds the JSONObject with the value I have passed in, I want to use the object to set a new value.
I have tried looping through the JSONArray and setting values in a model class and then getting from the same model class when the loop finds the value I am looking for.
I am a beginner programmer so I'm not sure if I am on the right track.
Here is the method I have been trying:
private String getTeamAbbrev(String jsonData, Integer opponentTeamId) {
Team[] teams = null;
String opponentAbbrev = null;
try {
JSONArray root = new JSONArray(jsonData);
teams = new Team[root.length()];
for (int i = 0; i < root.length(); i++){
JSONObject jsonTeam = root.getJSONObject(i);
Team team = new Team();
team.setTeamId(jsonTeam.getInt("team_id"));
team.setCity(jsonTeam.getString("city"));
team.setAbbrev(jsonTeam.getString("abbreviation"));
team.setFullName(jsonTeam.getString("team_name"));
teams[i] = team;
if(team.getTeamId() == opponentTeamId)) {
opponentAbbrev = team.getAbbrev();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return opponentAbbrev;
}
Here is the model class I have made:
public class Team {
private String mAbbrev;
private String mCity;
private Integer mTeamId;
private String mFullName;
public String getAbbrev() {
return mAbbrev;
}
public void setAbbrev(String abbrev) {
mAbbrev = abbrev;
}
public String getCity() {
return mCity;
}
public void setCity(String city) {
mCity = city;
}
public Integer getTeamId() {
return mTeamId;
}
public void setTeamId(Integer teamId) {
mTeamId = teamId;
}
public String getFullName() {
return mFullName;
}
public void setFullName(String fullName) {
mFullName = fullName;
}
}
JSON looks like this:
[ { "abbreviation" : "ATL",
"city" : "Atlanta",
"team_id" : 1610612737,
"team_name" : "Hawks"
},
{ "abbreviation" : "BOS",
"city" : "Boston",
"team_id" : 1610612738,
"team_name" : "Celtics"
},
{ "abbreviation" : "CLE",
"city" : "Cleveland",
"team_id" : 1610612739,
"team_name" : "Cavaliers"
},
{ "abbreviation" : "NOP",
"city" : "New Orleans",
"team_id" : 1610612740,
"team_name" : "Pelicans"
}]
Based on the "team_id" I have gotten from a separate api request, I want to get the value of the "abbreviation" key.
and here is the debug at line
if(team.getTeamId() == (opponentTeamId)) {opponentAbbrev = team.getAbbrev(); }
this = {oneonanyone.com.fantasybasketball_1onany1.MatchupActivity#831701908048}
jsonData = {java.lang.String#831708371144}"[ { "abbreviation" : "ATL",\n "city" : "Atlanta",\n "team_id" : 1610612737,\n "team_name" : "Hawks"\n },\n { "abbreviation" : "BOS",\n "city" : "Boston",\n "team_id" : 1610612738,\n "team_name" : "Celtics"\...
opponentTeamId = {java.lang.Integer#831708367536}"1610612740"
value = 1610612740
teams = {oneonanyone.com.fantasybasketball_1onany1.DataModel.Team[30]#831708408096}
[0] = {oneonanyone.com.fantasybasketball_1onany1.DataModel.Team#831708408232}
mAbbrev = {java.lang.String#831708378296}"ATL"
mCity = {java.lang.String#831708378536}"Atlanta"
mFullName = {java.lang.String#831708378944}"Hawks"
value = {char[5]#831708379008}
hashCode = 0
offset = 0
count = 5
mTeamId = {java.lang.Integer#831708408328}"1610612737"
opponentAbbrev = null
root = {org.json.JSONArray#831708378040}"[{"abbreviation":"ATL","team_id":1610612737,"team_name":"Hawks","city":"Atlanta"},{"abbreviation":"BOS","team_id":1610612738,"team_name":"Celtics","city":"Boston"},{"abbreviation":"CLE","team_id":1610612739,"team_name"...
values = {java.util.ArrayList#831708378096} size = 30
i = 0
jsonTeam = {org.json.JSONObject#831708378120}"{"abbreviation":"ATL","team_id":1610612737,"team_name":"Hawks","city":"Atlanta"}"
nameValuePairs = {java.util.HashMap#831708378136} size = 4
team = {oneonanyone.com.fantasybasketball_1onany1.DataModel.Team#831708408232}
mAbbrev = {java.lang.String#831708378296}"ATL"
mCity = {java.lang.String#831708378536}"Atlanta"
mFullName = {java.lang.String#831708378944}"Hawks"
mTeamId = {java.lang.Integer#831708408328}"1610612737"
teams[i] = {oneonanyone.com.fantasybasketball_1onany1.DataModel.Team#831708408232}
mAbbrev = {java.lang.String#831708378296}"ATL"
mCity = {java.lang.String#831708378536}"Atlanta"
mFullName = {java.lang.String#831708378944}"Hawks"
mTeamId = {java.lang.Integer#831708408328}"1610612737"
Thanks for any help!
You should not use == for String comparison.
Try this:
if(team.getTeamId().equals(opponentTeamId)) {
opponentAbbrev = team.getAbbrev().toString();
}
Good luck.

Rename map keys in GSON according to FieldNamingPolicy

Say I'm building my GSON object like this
new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
and now I want to deserialize the following JSON
{
"MyMap" : {
"Key1" : "Foo",
"Key2" : "Bar"
}
}
into the following class (which is working just fine)
public class MapClass {
Map<String,String> myMap;
}
but I also would like the keys to be named "key1" and "key2". How would I go about this?
You can try in this way:
try {
JSONObject jObj = new JSONObject("{"
+ " \"MyMap\" : {"
+ " \"Key1\" : \"Foo\","
+ " \"Key2\" : \"Bar\""
+ " }"
+ "}"); // this parses the json
JSONObject jObjt = jObj.getJSONObject("MyMap");
//old version with out GSON
Map<String, String> map = new HashMap();
Iterator itr = jObjt.keys();
while (itr.hasNext()) {
String key = (String) itr.next();
String value = jObjt.getString(key);
map.put(key, value);
}
//desalinized one with GSON
Map<String, String> map1 = new Gson().fromJson(jObjt.toString(), HashMap.class);
for (String str : map1.keySet()) {
System.out.println("k:" + str + " v:" + map1.get(str));
}
} catch (JSONException ex) {
//log the error
}
FieldNamingPolicy is applied to fields of json value. It is not possible to apply this to maps' keys (a map which has key, value pairs) at json.
Easy solution:
After deserialization, iterate over your map and rename key names. i.e. Key1 to key1 and Key2 to key2.
Other solution:
Write a custom TypeAdapter which handles deserialization process and renames keys.
public class MapClassTypeAdapter extends TypeAdapter<MapClass> {
#Override
public MapClass read(JsonReader in) throws IOException {
final MapClass mapClassInstance = new MapClass();
mapClassInstance.myMap = new HashMap<String, String>();
in.beginObject();
if("myMap".equalsIgnoreCase(in.nextName())) {
in.beginObject();
while (in.hasNext()) {
String key = in.nextName();
// You want keys as camel case
String newKey = key.substring(0,1).toLowerCase() + key.substring(1);
String value = in.nextString();
mapClassInstance.myMap.put(newKey, value);
}
in.endObject();
}
in.endObject();
return mapClassInstance;
}
#Override
public void write(JsonWriter out, MapClass mapClass) throws IOException {
throw new RuntimeException("MapClassTypeAdapter.write method not implemented yet!");
}
}
Test Other solution:
String json = "{\"myMap\":{\"Key1\":\"Foo\",\"Key2\":\"Bar\"}}";
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(MapClass.class, new MapClassTypeAdapter());
final Gson gson = gsonBuilder.create();
MapClass mapClass = gson.fromJson(json, MapClass.class);

How to Read Json File Without Giving Element Names in Java

I want to read json file as follow;
{
"M": {
"row": [
{
"col1": "c00"
},
{
"col1": "c10",
"col2": "c11"
},
{
"col1": "c20",
"col2": "c21",
"col3": "c22"
}
]
}
}
Next to reading, I want to print "c00","c10","c11","c20","c21","c22" but without giving element as "col1","col2","col3"...
Thanks for helping.
You can use org.json library for this. It is here. General idea:
JSONObject obj = new JSONObject(sourceString);
for(String key : obj.keys()){
String value = obj.getString(key);
// Process value here
}
Use any JSON parsing library such as GSON or Jackson and convert it into Java Object.
Sample code using GSON library
Type type = new TypeToken<Map<String, Object>>() {}.getType();
Map<String, Object> data = new Gson().fromJson(jsonString, type);
System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(data));
// get the desired value from map
Map<String,ArrayList<Map<String,String>>> mMap=(Map<String,ArrayList<Map<String,String>>>)data.get("M");
ArrayList<Map<String,String>> rowArray=mMap.get("row");
for(Map<String,String> colMap:rowArray){
for(String value:colMap.values()){
System.out.println(value);
}
}
You can convert JSON string into Java POJO class as well that is replica of the JSON string
class MDetails {
private MDetail M;
// getter & setter
}
class MDetail {
private ArrayList<Map<String, String>> row;
// getter & setter
}
...
MDetails data = new Gson().fromJson(jsonString, MDetails.class);
for (Map<String, String> colMap : data.getM().getRow()) {
for (String value : colMap.values()) {
System.out.println(value);
}
}
You can use different field name using #SerializedName annotation.
class MDetails {
#SerializedName("M")
private MDetail mDetail;
// getter & setter
}
As per comments, the keys are dynamic so iterate the map containing another map in it and print all the values whose key starts with col
sample code: (call below method that recursively iterate all keys and values)
public static void printColValues(Object data) {
if (data instanceof Map) {
for (Map.Entry<String, Object> entry : ((Map<String, Object>) data).entrySet()) {
String key = entry.getKey();
if (key.startsWith("col")) {
System.out.println(entry.getValue());
} else {
printColValues(entry.getValue());
}
}
} else if (data instanceof List) {
for (Object obj : (List) data) {
printColValues(obj);
}
}
}
output:
c00
c10
c11
c20
c21
c22
OR if nothing works then try with regex pattern but keep it as last resort
("col\d+":)("[^"]*")
Here is online demo
Or try with Reluctant Qualifier
("col\d+":)(".*?")
Here is demo
sample code:
String jsonString = "{\"M\":{\"row\":[{\"col1\":\"c00\"},{\"col1\":\"c10\",\"col2\":\"c11\"},{\"col1\":\"c20\",\"col2\":\"c21\",\"col3\":\"c22\"}]}}";
Pattern p = Pattern.compile("(\"col\\d+\":)(\"[^\"]*\")");
Matcher m = p.matcher(jsonString);
while (m.find()) {
System.out.println(m.group(2));
}
output:
"c00"
"c10"
"c11"
"c20"
"c21"
"c22"
Code updated to print all values regardless of keys
public static void printColValues(Object data) {
if (data instanceof Map) {
for (Map.Entry<String, Object> entry : ((Map<String, Object>) data).entrySet()) {
Object value=entry.getValue();
if (value instanceof String) {
System.out.println(value);
} else {
printColValues(value);
}
}
} else if (data instanceof List) {
for (Object obj : (List) data) {
printColValues(obj);
}
}
}

Categories