Reading JSON file using java [duplicate] - java

This question already has answers here:
How to parse JSON in Java
(36 answers)
Closed 4 months ago.
My issue is that I don't how to find that I have read the first JSON object of the JSON array leave_applicants. This I need to find using java.
{
"leave_applicants":[
{
"applicant_name" : "Jhon",
"supervisor_name" : "Mark",
"org" : "UNDP",
"index_no" : 1,
"leave_details": {
"leave_type" : "annual",
"from" : "12-07-2018",
"to" : "15-07-2018"
}
},
{
"applicant_name" : "Ravi",
"supervisor_name" : "Mark",
"org" : "UNDP",
"index_no" : 2,
"leave_details": {
"leave_type" : "sick_leave_cert",
"from" : "20-07-2018",
"to" : "25-07-2018"
}
}
]
}

Assuming the JSON is in a text file stored on your computer. See the following code and at the end of each iteration of the for loop the end of first JSON object of the JSON array will occur (as you wanted).
import java.io.FileReader;
import java.util.Iterator;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
public class ReadingJSONFromFile {
#SuppressWarnings("unchecked")
public static void main(String[] args) {
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader(
"Path/To/JSON/File/json_file.txt"));
JSONObject jsonObject = (JSONObject) obj;
JSONArray leaveApplicants = (JSONArray) jsonObject.get("leave_applicants");
for(Object applicants: leaveApplicants) {
JSONObject app = (JSONJObject)applicants;
String name = (String) app.get("applicant_name"); // Get the applicant name
// You can get the other keys of the object similarly and display them as you want
// This will be the end of the first object of the JSON Array
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Related

Concatenate all JSON key-value pairs into a String

I have input:
{
"Id": 200,
"TimeStamp": 1596466800,
"Animal": "cat"
}
I need to concatenate all key-value pairs in one String
I need output:
"Id200Timestamp1596466800Animalcat"
Usually you use a third-party library for parsing JSON. There are several. The below code uses Gson.
Note that the below code is not terribly robust, it assumes that there are no nested elements and that the values are all primitives. That is what you specifically asked for, i.e. specific input and specific output, and I am posting a solution that achieves what you specifically asked for.
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import java.util.Map;
import java.util.Set;
public class GsonTst0 {
public static void main(String[] args) {
String json = "{ \"Id\": 200, \"TimeStamp\": 1596466800, \"Animal\": \"cat\"}";
JsonElement root = JsonParser.parseString(json);
if (root.isJsonObject()) {
JsonObject jsonObj = root.getAsJsonObject();
Set<Map.Entry<String, JsonElement>> entries = jsonObj.entrySet();
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, JsonElement> entry : entries) {
sb.append(entry.getKey());
JsonElement elem = entry.getValue();
JsonPrimitive prim = elem.getAsJsonPrimitive();
if (prim.isNumber()) {
sb.append(prim.getAsBigDecimal());
}
else {
sb.append(prim.getAsString());
}
}
System.out.println(sb);
}
}
}
Running the above code prints the following:
Id200TimeStamp1596466800Animalcat

Get JSONArray without Arrayname in method

I need to get JSONArray from my data in string but without mentioning the arrayname as follows. It should get Array name itself from JSON data.
Here is my code
String metadata = result.getMetaData();
JSONObject jsonObject = new JSONObject(metadata);
JSONArray jsonArray = jsonObject.getJSONArray("Shoe2");
for(int i =0 ; i<jsonArray.length();++i) {
JSONObject rec = jsonArray.getJSONObject(i);
barcode = rec.getString("BarcodeId");
material=rec.getString("Material");
category=rec.getString("Category");
}
Baroode.setText(barcode);
Material.setText(material);
Category.setText(category);
Now what I need is get JSON arrayname "SHoes1" by itself rather than use explicit naming as I am doing so.
My JSON String looks like this
{
"Shoe2":[{
"BarcodeId" : "9770012345673",
" " : "Men",
"Material" : "Panther",
"ProductId" : "ND-TR-0089",
"ProductName" : "Black Retro"
}
]
}
Help will be appreciated :)
Lets assume you have your json in a file name test.json. If you have your array as first element of your root json you can access it via the code below :
package yourPackage;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Main {
public static void main(String[] args) throws IOException {
String metadata = new String(Files.readAllBytes(Paths.get("test.json")));
JSONObject jsonObject = new JSONObject(metadata);
JSONArray jsonArray = jsonObject.getJSONArray(jsonObject.keys().next().toString());
System.out.println(jsonArray.getJSONObject(0));
}
}
Output :
{" ":"Men","ProductName":"Black Retro","Material":"Panther","ProductId":"ND-TR-0089","BarcodeId":"9770012345673"}
test.json :
{
"Shoe2":[{
"BarcodeId" : "9770012345673",
" " : "Men",
"Material" : "Panther",
"ProductId" : "ND-TR-0089",
"ProductName" : "Black Retro"
}
]
}

Retrieve just one field from JSON string in Java

Is there a way to just one field from the JSON string? My code is as follows:
Object obj = parser.parse(resp);
System.out.println(obj);
JSONArray array = new JSONArray();
array.add(obj);
JSONObject obj2 = (JSONObject)array.get(0); //Getting NPE here
//Object obj3 = obj2.get("data");
System.out.println("Data: " + obj2.get("data"));
//System.out.println("Email: " + obj3.get("email_address"));
I'm using the following libraries
import org.json.simple.JSONObject;
import org.json.simple.JSONArray;
import org.json.simple.parser.ParseException;
import org.json.simple.parser.JSONParser;
From the response string resp, I just need data.email_address. I am unable to find a way to do it.
So if this is your input:
{
"data": {
"email_address": "example#example.com"
}
}
You first will need to make it a JSONObject:
JSONObject object = (JSONObject) new JSONParser().parse(json);
And then you can get data, another JSONObject:
JSONObject data = (JSONObject) object.get("data")
And from your data Object you can get email_address:
String email = data.get("email_address").toString();
If your input is an array of users, like this:
{
"users": [
{
"data": {
"email_address": "example#example.com"
}
},
{
"data": {
"email_address": "exapmle2#example2.com"
}
}
]
}
You can get it the same way:
JSONObject object = (JSONObject) new JSONParser().parse(json);
JSONArray users = (JSONArray) object.get("users");
JSONObject user0 = (JSONObject) users.get(0);
JSONObject user0data = (JSONObject) user0.get("data");
String email = user0data.get("email_address").toString();
First parse the whole JSON into an Object. Then get an array called users, from that array, get index 0. From that Object, get data, and then email_address
The other option is to use jsonpath.
Using the same Json blob as Lorant:
{
"data": {
"email_address": "example#example.com"
}
}
You would use the following expression.
$.data.email_address
Or if it was an array, simply.
$.users.[data].email_address
An online tool can be used to experiment and learn the syntax, but if you know xpath it should be somewhat familiar already.
import org.json.JSONObject;
JSONObject json = new JSONObject(record);
json.getString("fieldName"));

Jackson JSON Java nested object and arrays

I have an example nested json object like below :
{
"payload": {
"id": "1",
"apiResp": {
"apiRespDetails": {
"report": {
"reportId": "reportid1",
"reportDetails": [
{
"code": "1",
"rating": "good"
},
{
"code": "2",
"rating": "bad"
},
{
"code": "3",
"rating": "fair"
}
]
}
}
}
}
}
I only need the report object, I do not need any of its parent object details. What would be the best way to get just that using the Jackson API ?
I have created a Java Class called Report.java with fields reportId (String) and reportDetails(List of ReportDetail ) where ReportDetail is another class with String fields code , rating etc. Do I need to use some Deserializer, JsonTreeParser mechanism?Thanks.
The solution for this is jayway Java implementation for JsonPath.
JsonPath is the json equivalent for the XPath query language for XML.
the query langauge is quite powerful, as can be seen in the examples on the github readme.
Here is a quick demo to get you started:
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import com.jayway.jsonpath.*;
import net.minidev.json.JSONArray;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.*;
public class JsonPathDemo2
{
public static void main(String[] args)
{
// query: search for any report property below root
String jsonPathQuery = "$..report";
try (InputStream is = Files.newInputStream(Paths.get("C://temp/xx.json"))) {
Object parsedContent =
Configuration.defaultConfiguration().jsonProvider().parse(is, StandardCharsets.UTF_8.name());
System.out.println("hasJsonPath? " + hasJsonPath(jsonPathQuery).matches(parsedContent));
Object obj = JsonPath.read(parsedContent, jsonPathQuery);
System.out.println("parsed object is of type " + obj.getClass());
System.out.println("parsed object to-string " + obj);
JSONArray arr = (JSONArray)obj;
System.out.println("first array item is of type " + arr.get(0).getClass());
System.out.println("first array item to-string " + arr.get(0));
} catch (Exception e) {
e.printStackTrace();
}
}
}
output:
hasJsonPath? true
parsed object is of type class net.minidev.json.JSONArray
parsed object to-string [{"reportId":"reportid1","reportDetails":[{"code":"1","rating":"good"},{"code":"2","rating":"bad"},{"code":"3","rating":"fair"}]}]
first array item is of type class java.util.LinkedHashMap
first array item to-string {reportId=reportid1, reportDetails=[{"code":"1","rating":"good"},{"code":"2","rating":"bad"},{"code":"3","rating":"fair"}]}
Hi found two solutions using jackson fasterxml api.
In the first one you can just use the findValue method on the jsonNode and pass in the string value of property/object you are looking for
String jsonresponse = "above json string";
JsonFactory jsonFactory = new JsonFactory();
JsonParser jp = jsonFactory.createParser(jsonresponse);
jp.setCodec(new ObjectMapper());
JsonNode jsonNode = jp.readValueAsTree();
JsonNode reportNode = jsonNode.findValue("report");
ObjectMapper mapper = new ObjectMapper();
Report report = mapper.convertValue(reportNode, Report.class);
This other solution use JsonToken which travels the json response till you find what you are looking for
JsonFactory factory = new JsonFactory();
factory.setCodec(new ObjectMapper());
JsonParser parser = factory.createParser(jsonresponse);
while(!parser.isClosed()){
JsonToken jsonToken = parser.nextToken();
if(JsonToken.FIELD_NAME.equals(jsonToken)){
String fieldName = parser.getCurrentName();
if("report".equals(fieldName)) {
jsonToken = parser.nextToken();
Report report = parser.readValueAs(Report.class);
} else {
jsonToken = parser.nextToken();
}
}
}

How to convert a string to JSONArray

I am hitting an api and getting a string response. The response is something like this
"["VU","Vanuatu",["Pacific/Efate","(GMT+11:00) Efate"],"VN","Vietnam",["Asia/Saigon","(GMT+07:00) Hanoi"]]"
And i want to convert this string into a json array of below type
[{"id":"VN","name":"Vanuatu","timezones":[{"id":Pacific/Efate,"name":"(GMT+11:00) Efate}]},"id":"VN","name":"Vietnam",[{"id":"Asia/Saigon","name":"(GMT+07:00) Hanoi"}]]
Can someone help
Looking at your String response, I've created a regular expression that will create four groups out of your response.
DEMO
Assuming that your output would come always in groups of four (i.e., id, name and timezones_id, timezones_name), this regular expression, would extract 4 groups out of the input string that you've provided:
Regex:
"([^"]*)",\s*"([^"]*)",\s*\["([^"]*)",\s*"([^"]*)"\]
Matches
Match 1
Full match 1-56 `"VU", "Vanuatu", ["Pacific/Efate", "(GMT+11:00) Efate"]`
Group 1. 2-4 `VU`
Group 2. 8-15 `Vanuatu`
Group 3. 20-33 `Pacific/Efate`
Group 4. 37-54 `(GMT+11:00) Efate`
Match 2
Full match 58-111 `"VN", "Vietnam", ["Asia/Saigon", "(GMT+07:00) Hanoi"]`
Group 1. 59-61 `VN`
Group 2. 65-72 `Vietnam`
Group 3. 77-88 `Asia/Saigon`
Group 4. 92-109 `(GMT+07:00) Hanoi`
 
Now once you've extracted these 4 groups, You can simply add appropriately in ArrayList and List and create JSONArray out of those lists.
The following program is self-explanatory with the inputs and outputs.
Input
["VU","Vanuatu",["Pacific/Efate","(GMT+11:00) Efate"],"VN","Vietnam",["Asia/Saigon","(GMT+07:00) Hanoi"]]
Output
[{"timezones":{"name":"(GMT+11:00) Efate","id":"Pacific/Efate"},"name":"Vanuatu","id":"VU"},{"timezones":{"name":"(GMT+07:00) Hanoi","id":"Asia/Saigon"},"name":"Vietnam","id":"VN"}]
Formatted Output
[{
"id" : "VU",
"name" : "Vanuatu",
"timezones" : {
"name" : "(GMT+11:00) Efate",
"id" : "Pacific/Efate"
}
}, {
"id" : "VN",
"name" : "Vietnam",
"timezones" : {
"name" : "(GMT+07:00) Hanoi",
"id" : "Asia/Saigon"
}
}
]
Code
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.JSONArray;
import org.json.JSONException;
public class Test
{
public static void main(String[] args) throws IOException, JSONException {
String serverResponse = "[\"VU\", \"Vanuatu\", [\"Pacific/Efate\", \"(GMT+11:00) Efate\"], \"VN\", \"Vietnam\", [\"Asia/Saigon\", \"(GMT+07:00) Hanoi\"]]";
Map<String, Object> prop, innerProp;
List<Object> arr = new ArrayList<>(), obj;
String pattern = "\"([^\"]*)\",\\s*\"([^\"]*)\",\\s*\\[\"([^\"]*)\",\\s*\"([^\"]*)\"\\]";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(serverResponse);
while (m.find()) {
prop = new HashMap<>();
prop.put("id", m.group(1));
prop.put("name", m.group(2));
innerProp = new HashMap<>();
innerProp.put("id", m.group(3));
innerProp.put("name", m.group(4));
prop.put("timezones", innerProp);
arr.add(prop);
}
JSONArray jsonArray = new JSONArray(arr);
System.out.println(jsonArray.toString());
}
}
An option you have is to first create a JSONArray off of the string, and then read elements 3 by 3 from that array to create your output:
public static void main(String[] args) {
String input = "[\"VU\",\"Vanuatu\",[\"Pacific/Efate\",\"(GMT+11:00) Efate\"],\"VN\",\"Vietnam\",[\"Asia/Saigon\",\"(GMT+07:00) Hanoi\"]]";
JSONArray inputArray = new JSONArray(input);
JSONArray outputArray = new JSONArray();
for (int i = 0; i < inputArray.length(); i += 3) {
JSONObject obj = readCountry(inputArray, i);
outputArray.put(obj);
}
System.out.println(outputArray);
}
private static JSONObject readCountry(JSONArray array, int index) {
JSONObject country = new JSONObject();
country.put("id", array.getString(index));
country.put("name", array.getString(index + 1));
country.put("timezones", readTimeZones(array.getJSONArray(index + 2)));
return country;
}
private static JSONArray readTimeZones(JSONArray array) {
JSONArray timezones = new JSONArray();
JSONObject timezone = new JSONObject();
timezone.put("id", array.getString(0));
timezone.put("name", array.getString(1));
timezones.put(timezone);
return timezones;
}
You may add some error handling to fail gracefully or even recover with best effort if the input doesn't match.

Categories

Resources