Extract a part of the JSON object in JAVA - java

This is the sample of a JSON object. I want to extract the part of it and display those values in a jTable (SWING) in JAVA. Keys as table column names and values as row data respectively.
[
{
"_id":{
"date":"xxxxxxxx",
"time":"xxxxxxx",
"inc":"xxxx"
},
"DOCUMENTS":[
{
"EName":"John",
"eAge":"25",
"eAddress":"UK"
},
{
"EName":"Alex",
"eAge":"24",
"eAddress":"Australia"
}
]
}
]
I want to extract this part.
[
{
"EName":"John",
"eAge":"25",
"eAddress":"UK"
},
{
"EName":"Alex",
"eAge":"24",
"eAddress":"Australia"
}
]
I used this way to get the answer. Here jsonstring is the string that contains above data.
String[] splits = jsonString.split("DOCUMENTS\":");
String[] splits2 = splits[1].split("\\}]", 2);
System.out.println("spilted :"+splits2[0]);
but it is giving me the answer as
[{"EName":"John","eAge":"25","eAddress":"UK"},
{"EName":"Alex","eAge":"24","eAddress":"Australia"
it removed the closed square bracket.
How can I get the correct answer? Your help is much appreciated.

Take a look at this simple tutorials:
http://wiki.fasterxml.com/JacksonInFiveMinutes
http://www.tutorialspoint.com/json/json_java_example.htm
example:
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
public class KroplaTest {
private static final String JSON = "{\"id\":{ "
+ "\"date\":\"xxxxxxxx\","
+ "\"time\":\"xxxxxxx\","
+ "\"inc\":\"xxxx\""
+ "},"
+ "\"documents\":["
+ "{"
+ " \"eName\":\"John\","
+ " \"eAge\":\"25\","
+ " \"eAddress\":\"UK\""
+ "},"
+ "{"
+ " \"eName\":\"Alex\","
+ " \"eAge\":\"24\","
+ " \"eAddress\":\"Australia\""
+ "} ]} ";
public static void main(String[] args) {
final ObjectMapper mapper = new ObjectMapper();
try {
Map<String,Object> map = new HashMap<String,Object>();
map = mapper.readValue(JSON, new TypeReference<HashMap<String,Object>>(){});
System.out.println(map.get("documents").toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
This will print to sysout:
[{eName=John, eAge=25, eAddress=UK}, {eName=Alex, eAge=24, eAddress=Australia}]

Instead of using split(), use:
int index= splits[1].indexOf("\\}]");
String result = splits[1].substring(0,index);

Related

JsonPath expression to find if a key-value pair is not present in a set of JSON objects?

Given the following JSON:
{
"full_report": {
"score": "5",
"history": {
"record": [
{
"name": "John Smith",
"SSN": "123456789",
"last_visit": "02.03.2019",
"expiry_date": "15.03.2019"
},
{
"name": "John Doe",
"SSN": "987654321",
"last_visit": "05.03.2019",
"expiry_date": "15.09.2019"
},
{
"name": "Jane Doe",
"SSN": "999999999",
"last_visit": "02.03.2019"
}
]
}
}
}
I would like to be able to use JsonPath to find if any of the objects under the record array are missing the expiry_date key and value pair. I currently have a working solution using a method that adds all entries of record to one list and all entries of expiry_date to another and simply checks if the subtraction of both list sizes equals 0 to return a boolean value.
public Boolean isMissing(String json, String expression) {
String[] expr = expression.split(";");
List<String> totalRecords = JsonPath.read(json, expr[0]);
List<String> foundRecords = JsonPath.read(json, expr[1]);
return totalRecords.size() - foundRecords.size() != 0;
}
This requires using two JsonPath expressions with a ; delimiter like so which causes some other, unrelated issues that I'd like to avoid:
$.full_report.history.record[?(#.expiry_date)];$.full_report.history.record[*]
For a copy of this exact structure in XML I can use an XPath expression like so: boolean(full_report/history/record[not(expiry_date/text())])
Any chance there's an equivalent filter that I may have missed in JsonPath?
Update
The answer below by Saeed Alizadeh to use predicate does not solve the problem of having to pass in the property to look for in the first place.
It did help make the method and passing in the property a fair bit cleaner as there's no longer a need to write two separate expressions rather than expression;property_to_lookup. As seen in the method below, that fundamental issue still remains but is much more hassle-free:
public Boolean isMissing(String json, String expression) {
String[] expressionAndPredicate = expression.split(";");
Predicate missingKeyValue = predicateContext -> {
Object missingKey = predicateContext.item(Map.class).get(expressionAndPredicate[1]);
return missingKey == null || missingKey.toString().length() <= 0;
};
List<String> records = JsonPath.read(json, expressionAndPredicate[0], missingKeyValue);
return records.size() != 0;
}
I don't want to add a 3rd parameter to the method for the property nor split the incoming string to sidestep the issue as it creates some issues when providing the JsonPath expression as input at the endpoint. If no one-line expression exists similar to the XPath example, I'll mark the question as answered by Saeed.
As you can see example below by using predicate you can filter result:
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Predicate;
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String[] args) {
String json = "{\n" +
" \"full_report\": {\n" +
" \"score\": \"5\",\n" +
" \"history\": {\n" +
" \"record\": [\n" +
" {\n" +
" \"name\": \"John Smith\",\n" +
" \"SSN\": \"123456789\",\n" +
" \"last_visit\": \"02.03.2019\",\n" +
" \"expiry_date\": \"15.03.2019\"\n" +
" },\n" +
" {\n" +
" \"name\": \"John Doe\",\n" +
" \"SSN\": \"987654321\",\n" +
" \"last_visit\": \"05.03.2019\",\n" +
" \"expiry_date\": \"15.09.2019\"\n" +
" },\n" +
" {\n" +
" \"name\": \"Jane Doe\",\n" +
" \"SSN\": \"999999999\",\n" +
" \"last_visit\": \"02.03.2019\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" }\n" +
"}";
Predicate expiry_date = new Predicate() {
public boolean apply(PredicateContext predicateContext) {
Object expiry_date = predicateContext.item(Map.class).get("expiry_date");
return expiry_date != null && expiry_date.toString().length() > 0 ? false : true;
}
};
List records = JsonPath.parse(json).read("full_report.history.record[?]", List.class, expiry_date);
System.out.println(records);
}
}
this will print following output as the only record missing "expiry_date" property
[{"name":"Jane Doe","SSN":"999999999","last_visit":"02.03.2019"}]
update
public static boolean isMissing(String json, final String jsonProperty) {
Predicate predicate = new Predicate() {
public boolean apply(PredicateContext predicateContext) {
Object propertyObject = predicateContext.item(Map.class).get(jsonProperty);
return propertyObject != null && propertyObject.toString().length() > 0 ? false : true;
}
};
List records = JsonPath.parse(json).read("full_report.history.record[?]", List.class, predicate);
return (records != null && records.size() > 0) ? true : false;
}
output:
System.out.println(isMissing(json, "expiry_date")); // prints true
System.out.println(isMissing(json, "name")); // prints false

Deserialize a complex JSON Object into a POJO using GSON

I'm getting the following JSON response from IMDB.
{
"Search":
[
{
"Title":"Seven Pounds",
"Year":"2008",
"imdbID":"tt0814314",
"Type":"movie",
"Poster":"someUrl"
},
{
"Title":"Seven Samurai",
"Year":"1954",
"imdbID":"tt0047478",
"Type":"movie",
"Poster":"someUrl"
}
],
"totalResults":"1048",
"Response":"True"
}
I'd like to extract every movie and store it into a List so I've created a class MovieContainer with a List of Movies, where each Movie contains String attributes describing details about said movie e.g. title, year yiddi yadda - you get the drill!
I used the following code snippet to;
MovieContainer cnt = new Gson().fromJson(jstring, MovieContainer.class);
where jstring is a valid json string similar to the json string sample above, but when I try to iterate over the List in the MovieContainer instance I get a NullPointerException.
I'm new to GSON hence not sure what's the cause?
EDIT: I do know what a NullPointerException is, but I don't understand why Java throws it in my example.
My MovieContainer class:
public class MovieContainer {
public List<Movie> movies;
}
My Movie class:
public class Movie {
String Title;
String Year;
String Poster;
String imdbID;
String Type;
}
I'm expecting the call to the fromJson method to fill my List with the information matching the fields' name, but the List movies points is null.
If you want to search for titles first you need to get "Search" inside that data you need to iterate and look for titles.
Because your Gson contains 3 elements, "Search", "totalResults" and "Response".
Your MovieContainer class is missing the other two fields i.e. totalResults and Response which are also part of the root json object.
Here's a quick dirty example to get you up and running. It's based on the information you have provided thus far.
Movie.java
public class Movie {
private String Title;
private String Year;
private String imdbID;
private String Type;
private String Poster;
}
MovieContainer.java
public class MovieContainer {
private List<Movie> Search;
private String totalResults;
private String Response;
public static void main(String[] args) {
// Converts the json to the Java object a.k.a POJO 😎!!!
deserialize();
}
private static void deserialize() {
String jstring = " { " +
" 'Search' : [ " +
" { " +
" 'Title' : 'Seven Pounds', " +
" 'Year' : '2008', " +
" 'imdbID' : 'tt0814314', " +
" 'Type' : 'movie', " +
" 'Poster' : 'someUrl' " +
" }, " +
" { " +
" 'Title' : 'Seven Samurai', " +
" 'Year' : '1954', " +
" 'imdbID' : 'tt0047478', " +
" 'Type' : 'movie', " +
" 'Poster' : 'someUrl' " +
" } " +
" ], " +
" 'totalResults' : '1048', " +
" 'Response' : 'True' " +
" } ";
Gson gson = new Gson();
MovieContainer searchResults = gson.fromJson(jstring, MovieContainer.class);
}
}
A screenshot to confirm the List isn't null are as follows:-
Now time to party see ya!!! 🎉🎉🎉🎉🎉

Access to the elements of Array of Jsons

I have seen many examples, but none of them are not like what i want.
Consider I have a JSONObject like:
[ {
"id" : "572add95e4b0b04f4d502a3c",
"amount" : 109.27,
"sourceCurrency" : "MXN",
"targetCurrency" : "USD",
"recipientBankId" : "572add95e4b0b04f4d502a37",
"iban" : "5805742027",
"created" : "2016-05-05T05:43:49.194"
}, {
"id" : "572add95e4b0b04f4d502a3e",
"amount" : 722.41,
"sourceCurrency" : "GBP",
"targetCurrency" : "INR",
"recipientBankId" : "572add95e4b0b04f4d502a32",
"iban" : "4688276585",
"created" : "2016-05-05T05:43:49.2"
}]
and i want to access to the second json and iban value.
How can i do it?
With your json content
String json = "[ {\n" +
" \"id\" : \"572add95e4b0b04f4d502a3c\",\n" +
" \"amount\" : 109.27,\n" +
" \"sourceCurrency\" : \"MXN\",\n" +
" \"targetCurrency\" : \"USD\",\n" +
" \"recipientBankId\" : \"572add95e4b0b04f4d502a37\",\n" +
" \"iban\" : \"5805742027\",\n" +
" \"created\" : \"2016-05-05T05:43:49.194\"\n" +
"}, {\n" +
" \"id\" : \"572add95e4b0b04f4d502a3e\",\n" +
" \"amount\" : 722.41,\n" +
" \"sourceCurrency\" : \"GBP\",\n" +
" \"targetCurrency\" : \"INR\",\n" +
" \"recipientBankId\" : \"572add95e4b0b04f4d502a32\",\n" +
" \"iban\" : \"4688276585\",\n" +
" \"created\" : \"2016-05-05T05:43:49.2\"\n" +
"}]";
You first need to get a JSONArray from your json content :
JSONArray array = new JSONArray(json);
Then you read the second ( at the index 1 ) JSONObject within the array:
JSONObject o = array.getJSONObject(1);
And finally you read the iban from the JSONObject :
String secondIban = o.getString("iban");
System.out.println(secondIban);
With of course all this surrounded with a try/catch to catch JSONException:
try {
JSONArray array = new JSONArray(json);
JSONObject o = array.getJSONObject(1);
String secondIban = o.getString("iban");
System.out.println(secondIban);
}catch(JSONException jse){
jse.printStackTrace();
}
Note
If you want to be aware that the iban field doesn't exist use o.getString("iban").
A JSONException will be thrown if the field is missing.
If you are okay to work with an empty string "" as default value for the eventually missing field then use o.optString("iban") to read the field.
you can do something like below.
public static void main(String[] args) {
String json = "[{\n" +
" \"id\" : \"572add95e4b0b04f4d502a3c\",\n" +
" \"amount\" : 109.27,\n" +
" \"sourceCurrency\" : \"MXN\",\n" +
" \"targetCurrency\" : \"USD\",\n" +
" \"recipientBankId\" : \"572add95e4b0b04f4d502a37\",\n" +
" \"iban\" : \"5805742027\",\n" +
" \"created\" : \"2016-05-05T05:43:49.194\"\n" +
"}, {\n" +
" \"id\" : \"572add95e4b0b04f4d502a3e\",\n" +
" \"amount\" : 722.41,\n" +
" \"sourceCurrency\" : \"GBP\",\n" +
" \"targetCurrency\" : \"INR\",\n" +
" \"recipientBankId\" : \"572add95e4b0b04f4d502a32\",\n" +
" \"iban\" : \"4688276585\",\n" +
" \"created\" : \"2016-05-05T05:43:49.2\"\n" +
"}]";
JSONArray objects = new JSONArray(json);
System.out.println(((JSONObject)objects.get(1)).get("iban"));
}
Use optString instead getString.
optString - Will return blank string if element/key not found in JSON.
getString - Will throw an exception.
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
================================
public static void main(String[] args) throws JSONException {
String str = "[{\"id\":\"572add95e4b0b04f4d502a3c\",\"amount\":109.27,\"sourceCurrency\":\"MXN\",\"targetCurrency\":\"USD\",\"recipientBankId\":\"572add95e4b0b04f4d502a37\",\"iban\":\"5805742027\",\"created\":\"2016-05-05T05:43:49.194\"},{\"id\":\"572add95e4b0b04f4d502a3e\",\"amount\":722.41,\"sourceCurrency\":\"GBP\",\"targetCurrency\":\"INR\",\"recipientBankId\":\"572add95e4b0b04f4d502a32\",\"iban\":\"4688276585\",\"created\":\"2016-05-05T05:43:49.2\"}]";
JSONArray jsonArray = new JSONArray(str);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.optJSONObject(i);
/* optString - will return blank string if element not found */
String iban = jsonObject.optString("iban");
System.out.println(iban);
}
}
What you should do is transform string into json:
public JsonObject parseJsonString(String jsonString) {
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject) jsonParser.parse(jsonString);
return jsonObject;
}
then extract values that you are after:
final String iban = jsonObject.get("iban").getAsString();
To read a value from JSON you can only with the next methods:
Data bind
Tree Model
Streaming API
XPath like
Which method to use is up to you because all methods have advantage and disadvantage.
Engines:
Fastjson supports Data bind, XPath like
Gson supports Data bind, Tree Model, Streaming API
Jackson supports Data bind, Tree Model, Streaming API
JsonPath supports XPath like
Genson supports Data bind, Tree model with Jsonp, Streaming API
Ig json parser supports Data bind
Moshi supports Data bind
JSON java supports Tree Model
LoganSquare supports Data bind
I guess you want to select only a part from json, so xpath like could be your choice with syntax like this $[1].iban (JsonPath)

Why JSON Parser is giving, error org.json.JSONException: Expected a ':' after a key at 5 [character 6 line 1]

I am new in json and I have to get the value from web service response. I have used org.json library for this.Below is the sample json value:
{"tms_guid": "9LaHmoHpmTd811R",
   "recharge_status": "100",
   "message": "Transaction Successful",
   "response_time": {
      "verifyClient": 0.0281,
      "verifyGuid": 0.8695,
      "verifyOperator": 0.8698,
      "verifyMsid": 0.8698,
      "tms_guid": 1.6971,
      "queryErr": 7.4243,
      "StoringRecharge": 7.4358,
      "UpdatingBalance": 7.448
   }
}
My parsing JSON input string is :
private final static String JSON_TEST_DATA
= "{"
+ "   \"tms_guid\": \"9LaHmoHpmTd811R\", "
+ "   \"recharge_status\": \"100\", "
+ "   \"message\": \"Transaction Successful\", "
+ "   \"response_time\": { "
+ "      \"verifyClient\": 0.0281, "
+ "      \"verifyGuid\": 0.8695, "
+ "      \"verifyOperator\": 0.8698,"
+ "      \"verifyMsid\": 0.8698,"
+ "      \"tms_guid\": 1.6971,"
+ "      \"queryErr\": 7.4243,"
+ "      \"StoringRecharge\": 7.4358,"
+ "      \"UpdatingBalance\": 7.448"
+ "   }"
+ "}";
public static void main(final String[] argv) throws JSONException {
System.out.println(JSON_TEST_DATA);
final JSONObject testObj = new JSONObject(JSON_TEST_DATA);
System.out.println(testObj.toString());
}
Exception is as follows:
Exception in thread "main" org.json.JSONException: Expected a ':' after a key at 5 [character 6 line 1]
at org.json.JSONTokener.syntaxError(JSONTokener.java:432)
at org.json.JSONObject.<init>(JSONObject.java:206)
at org.json.JSONObject.<init>(JSONObject.java:310)
at com.kalsym.wsp.sp.icebeep.TestIceBeep.main(TestIceBeep.java:73)
I have seen similar post. But could not figure about the solution.
I am not seeing any problem. I have used same your code, but i am able to execute your program :
You can see my code, I have useed same java api too.
import org.json.JSONException;
import org.json.JSONObject;
public class TestCode {
private final static String JSON_TEST_DATA
= "{"
+ " \"tms_guid\": \"9LaHmoHpmTd811R\", "
+ " \"recharge_status\": \"100\", "
+ " \"message\": \"Transaction Successful\", "
+ " \"response_time\": { "
+ " \"verifyClient\": 0.0281, "
+ " \"verifyGuid\": 0.8695, "
+ " \"verifyOperator\": 0.8698,"
+ " \"verifyMsid\": 0.8698,"
+ " \"tms_guid\": 1.6971,"
+ " \"queryErr\": 7.4243,"
+ " \"StoringRecharge\": 7.4358,"
+ " \"UpdatingBalance\": 7.448"
+ " }"
+ "}";
public static void main (String arg[]) throws JSONException{
//System.out.println(JSON_TEST_DATA);
final JSONObject testObj = new JSONObject(JSON_TEST_DATA);
System.out.println(" --"+testObj.getString("recharge_status")+"\n");
System.out.println(testObj.toString());
}
}
may be some char-set problem.
I just had a similar problem, turned out that the JSON string copied from another place contained non-breaking space characters, hard to notice even under a debugger :). I was removing HTML tags from that string (received via email) with:
jstr = jstr.replaceAll("<.*?>", ""); // removes anything between < and >
and the result looked like valid JSON, but with these non-breaking spaces... This helped:
jstr = jstr.replaceAll("<.*?>|\u00a0", "");

Regex getting a specific part of a string only

I am trying to get for example only this:
-68.06993865966797
from a output of this type:
{
"results" : [
{
"elevation" : -68.06993865966797,
"location" : {
"lat" : 27.85061,
"lng" : -95.58962
},
"resolution" : 152.7032318115234
}
],
"status" : "OK"
}
How is it possible to only get the string after
"elevation" :
and end with a comma, but get the string inbetween the colon after elevation until the comma that ends the line
Using regex is not recommended for JSON data. Despite that, I put the two ways (i.e. regex and JSON parser) together as follows:
import java.util.regex.*;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public static void main(String[] args) throws JSONException {
String JSON_DATA = "{\n"+
" \"results\" : [\n"+
" {\n"+
" \"elevation\" : -68.06993865966797,\n"+
" \"location\" : {\n"+
" \"lat\" : 27.85061,\n"+
" \"lng\" : -95.58962\n"+
" },\n"+
" \"resolution\" : 152.7032318115234\n"+
" }\n"+
" ],\n"+
" \"status\" : \"OK\"\n"+
"}\n"+
"";
// 1. If using REGEX to find all values of "elevation".
Matcher m = Pattern.compile("\"elevation\"\\s+:\\s+(-?[\\d.]+),").matcher(JSON_DATA);
while (m.find()) {
System.out.println("elevation: " + m.group(1));
}
// 2. If using a JSON parser
JSONObject obj = new JSONObject(JSON_DATA);
JSONArray geodata = obj.getJSONArray("results");
for (int i = 0; i < geodata.length(); ++i) {
final JSONObject site = geodata.getJSONObject(i);
System.out.println("elevation: " + site.getDouble("elevation"));
}
}

Categories

Resources