Format of the following response? - java

I'm using Bing's auto suggest feature to auto suggest me terms given a query. You can find the tool here: http://api.bing.com/osjson.aspx?query=pe as you can see it's returning a strange format that isn't quite JSON. Is this a specific standard different to JSON? I've attempted parsing it as JSON using...
InputStream i = new URL(url).openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(i, Charset.forName("UTF-8")));
JSONObject json = new JSONObject(readAll(reader));
but I get the error A JSONObject text must begin with '{' found:" at 2 [character 3 line 1]
readAll =
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}

Your example is valid JSON:
["pe",["people","people search","petsmart","petco","petfinder","pep boys","people finder","people of walmart"]]
It is not object, it is array, which contains string at the first position and another array at the second. So try parse as JSONArray, not as JSONObject.

A JSON Object starts with a { and ends with a }, which a JSONObject class was designed to parse.
A JSON Array starts with a [ and ends with a ], which a JSONArray class was designed to parse.
I hope this helps.

Related

When streaming a Json file with GSON's JsonReader, can you dump an object to string?

I am working in Java using the GSON library to process a huge JSON document.
I absolutely cannot load this into memory, it is upwards of 8G and will crash the JVM with an OOM if I try to.
So I use JsonReader to process the stream of JSON.
There are certain times when I reach a BEGIN_OBJECT that want to just dump the contents of the object to string instead of processing each individual element.
For example, I am parsing something like this:
[ { "SchemaVersion":"15.0.0.0","LibraryVersion":"16.0.7324.1200","ErrorInfo":{ "ErrorMessage":"Access denied. You do not have permission to perform this action or access this resource.","ErrorValue":null,"TraceCorrelationId":"03ab459e-7076-5000-c1a7-196f1fc54384","ErrorCode":-2147024891,"ErrorTypeName":"System.UnauthorizedAccessException" },"TraceCorrelationId":"03ab459e-7076-5000-c1a7-196f1fc54384" } ]
When I get to ErrorInfo, I just want that as a string instead of parsed out. I don't want to have to parse each piece.
So here is the code:
try (InputStream is = (InputStream)response.getEntity();
InputStreamReader inputStreamReader = new InputStreamReader(is);
JsonReader jsonReader = new JsonReader(inputStreamReader)) {
if (jsonReader.peek() != JsonToken.BEGIN_ARRAY) {
return;
}
jsonReader.beginArray();
while (jsonReader.hasNext()) {
jsonReader.beginObject(); // Start of the default object on every request
jsonReader.skipValue(); // name SchemaVersion
jsonReader.skipValue(); // value
jsonReader.skipValue(); // name LibraryVersion
jsonReader.skipValue(); // value
jsonReader.skipValue(); // name ErrorInfo
if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) {
// I want to dump the upcoming object to string here
...
Is it possible to dump the contents of the json reader for a given begin object until it ends to string?
Similar question, but not quite the same: Get a dump of a section (object) of JSON
Special thanks to https://stackoverflow.com/users/3389828/nikhil for the answer in the comments. You can use Gson.fromJson(jsonReader, Map.class) for this exact situation.
Gson gson = new Gson();
try (InputStream is = (InputStream)response.getEntity();
InputStreamReader inputStreamReader = new InputStreamReader(is);
JsonReader jsonReader = new JsonReader(inputStreamReader)) {
if (jsonReader.peek() != JsonToken.BEGIN_ARRAY) {
return;
}
jsonReader.beginArray();
while (jsonReader.hasNext()) {
Map header = gson.fromJson(jsonReader, Map.class);
if (header.get("ErrorInfo") != null) {
String errorDump = ((Map)header.get("ErrorInfo")).toString();
// Now I have the error dump I need but I also
// didn't load the entire thing into memory!
...
more info: https://javadeveloperzone.com/java-8/java-parse-large-json-file-gson-example/

Parse JSON for first instance of repeated data field in Java with org.JSON

I'm trying to parse the first instance of "actualEPS" from the following JSON file:
{"symbol":"AAPL","earnings":[{"actualEPS":2.34,"consensusEPS":2.17,"estimatedEPS":2.17,"announceTime":"AMC","numberOfEstimates":10,"EPSSurpriseDollar":0.17,"EPSReportDate":"2018-07-31","fiscalPeriod":"Q3 2018","fiscalEndDate":"2018-06-30","yearAgo":1.67,"yearAgoChangePercent":0.40119760479041916,"estimatedChangePercent":0.29940119760479045,"symbolId":11},{"actualEPS":2.73,"consensusEPS":2.69,...}
Here is the method currently. I know I'm getting data from the target as I can Sysout the String "inputLine" and see the full file. I'm having trouble parsing from that point. I have installed and imported the org.JSON library.
public static void getData(String s) throws Exception {
String urlBase = new String(theWebSiteImGettingDataFrom)
URL targetURL = new URL(urlBase);
URLConnection yc = targetURL.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
} // end while
in.close();
JSONObject obj = new JSONObject(inputLine);
double eps = obj.getJSONObject("earnings").getDouble("actualEPS");
System.out.println("This is the first instance of EPS: " + eps);
} // end getData method
I'm getting a Null Pointer Exception in the stack trace:
at org.json.JSONTokener.<init>(JSONTokener.java:94)
at org.json.JSONObject.<init>(JSONObject.java:357)
at code.URLConnectionReader.getData(URLConnectionReader.java:39)
How do I parse the data for the first instance of "actualEPS" and only the first instance?
EDIT
JSONObject obj = new JSONObject(inputLine);
JSONArray earningsArray = obj.getJSONArray("earnings");
JSONObject firstEPS = earningsArray.getJSONObject(0);
double eps = firstEPS.getDouble("actualEPS");
System.out.println("This is the first instance of EPS: " + eps);
First of all, as I have no idea how big your json is and as you only want to parse a specific part of the json itself, I would recommend you to use JsonReader.class instead of JsonObject.class.
Short difference:
JsonObject parses the whole json into RAM and needs to be smaller than 1 MB.
JsonReader uses a streaming approach, which allows you to handle big jsons more efficiently.
Secondly, if you know that you ALWAYS just need the first instance of your json you could simply shorten your jsonString itself before parsing it (e.g. substring, etc.).
Now to your code:
public static void getData(String s) throws Exception {
String urlBase = new String(theWebSiteImGettingDataFrom); // Semicolon!
URL targetURL = new URL(urlBase);
URLConnection yc = targetURL.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
} // end while
in.close();
System.out.println("My json: "+inputLine); //TODO: What is your output here?
JSONObject obj = new JSONObject(inputLine);
double eps = obj.getJSONObject("earnings").getDouble("actualEPS");
System.out.println("This is the first instance of EPS: " + eps);
} // end getData method
Please comment, as I can't tell if you get the json from your server.
EDIT:
Your error is in this line:
double eps = obj.getJSONObject("earnings").getDouble("actualEPS");
In short it should be like this:
double eps = obj.getJSONArray("earnings").getJSONObject(0).getDouble("actualEPS");
But, why? Your attribute earnings returns an JSONArray (Which means that you have multiple rows with indizes). So, instead of just requesting "earnings" as a JSONObject, you should rather use it as a JSONArray and then extract the first row (= .getJSONObject(0)). After extracting the first row you can actually use your double-Value.
I hope this works :)
2nd Edit:
Change that ..
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine); } // end while
to:
while ((inputLine += in.readLine()) != null) {
System.out.println(inputLine); } // end while
Your while loop keeps iterating until .readLine() returns null.
As null is the last iteration, you have only null in your variable.
As suggested you can solve that by simply changing the = to +=.
I hope we got it now. :)

Converting JSON to XML gives invalid XML

I am trying to convert a valid JSON file to XML.
InputStream is = new FileInputStream(file);
BufferedReader buf = new BufferedReader(new InputStreamReader(is));
String line = buf.readLine(); StringBuilder sb = new StringBuilder();
while(line != null){
sb.append(line);
line = buf.readLine();
}
//form the string
String jsonStr = sb.toString();
//save to xml
JSONParser parser = new JSONParser();
JSONObject json = (JSONObject) parser.parse(jsonStr);
String xml = XML.toString(json);
Here is my dependencies:
import org.json.XML;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
The input JSON is like this:
{"created":"2016-12-22T10:46:40.584Z","createdBy":"ish"}
The output XML looks like:
"{"createdBy":"ish","created":"2016-12-22T10:46:40.584Z"}"
Your problem is that you mix two APIs : json-simple and org.json.
Here :
String xml = XML.toString(json);
You pass a org.json.simple.JSONObject object to the org.json.XML.toString(Object) method.
What you want to pass is a org.json.JSONObject.
Actually, you don't need to use json-simple as you can create a JSONObject with org.json and more particularly a org.json.JSONObject. Which finally is a very good thing as XML.toString() would produce the expected result with an instance of that.
So change your code such as :
JSONObject json = new JSONObject(jsonStr);
String xml = XML.toString(json);
Optionally you can add the tag name of the enclosing element :
String xml = XML.toString(json, "foo");
Note that XML.toString(Object) is not necessary a very good designed API.
It accepts an Object as parameter and so relies on instanceof to apply the suitable processing.
The mapping to XML is done only if the parameter type belongs to some specific types : org.json.JSONObject, org.json.JSONArray, Java array.
And if it is not the case, a single thing is do : special characters are escaped such as ". As a org.json.simple.JSONObject doesn't make part of the expected type, the " of the JSONObject parameter were kept and the escaping converted them to ". Whereas the weird result you get :
"{"createdBy":"ish","created":"2016-12-22T10:46:40.584Z"}"

Unexpected token END OF FILE at position 0 while parsing JSON

In order to find out weather the JSON element is JSONArray or JSONObject type, I am getting Unexpected token END OF FILE at position 0 error.
My JSON is:
{"colors":[{"color":"red","value":"#00"},{"color":"white","value":"#000g"}]}
My code is:
java.io.FileReader reader = new java.io.FileReader("jsonpath");
org.json.simple.parser.JSONParser parser = new JSONParser();
System.Out.Println("aaaaaa JSON Class: "+parser.parse(reader).getClass());
if(parser.parse(reader) instanceof org.json.simple.JSONArray)
System.Out.Println("JSONArray");
else if(parser.parse(reader) instanceof org.json.simple.JSONObject)
System.Out.Println("JSONObject");
When I run above code it shows this output
aaaaaa JSON Class: class org.json.simple.JSONObject Unexpected token END OF FILE at popsition 0
at org.json.simple.parser.JSONParser(Unknown Source)
.
.
.
<rest of the exception>
I don't understand why this exception is occurring.
Please help me out.
Some more details after edit:
My this code is working fine with the given json file:
java.io.FileReader reader = new java.io.FileReader("jsonpath");
org.json.simple.parser.JSONParser parser = new JSONParser();
org.json.simple.JSONObject object = (JSONObject)parser.parse(reader);
System.Out.Println("JSONObject: "+object);
org.json.simple.JSONArray array = (JSONArray)object.get("colors");
System.Out.Println("JSONArray: "+array);
Output of above code:
JSONObject: {"colors":[{"color":"red","value":"#00"},{"color":"white","value":"#000g"}]}
JSONArray: [{"color":"red","value":"#00"},{"color":"white","value":"#000g"}]
But I want to dynamically parse the JSON without knowing the JSON structure.
I want to do something like this:
if(json is object)
JSONObject object = (JSONObject)parser.parse(reader);
else if (json is array)
JSONArray array = (JSONArray)parser.parse(reader);
Thanks.
You're repeatedly parsing the same Reader. The first call exhausts it and then each subsequent call sees an empty stream.
Parse the reader only once. Here is the working code:
java.io.FileReader reader = new java.io.FileReader("jsonpath");
org.json.simple.parser.JSONParser parser = new JSONParser();
Object p = parser.parse(reader);
if(p instanceof org.json.simple.JSONArray){
System.Out.Println("JSONArray");
org.json.simple.JSONArray object = (JSONArray)p;
}
else if(p instanceof org.json.simple.JSONObject){
System.Out.Println("JSONObject");
org.json.simple.JSONObject object = (JSONObject)p;
}
Output of above code
JSONObject
Well, error may occur when you try to pass wrong path.
So check your path to json file properly. Try to use absolute path at first.
Here is my procedure:
private static void ReadWithEncoding(String filePath, String encoding) {
StringBuilder json = new StringBuilder();
File f = new File(filePath);
if (f.exists() && f.isFile()) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f), encoding));
String line;
while ((line = br.readLine()) != null) {
json.append(line);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(json);
}
}
You may run it like this for UTF8:
ReadWithEncoding("D:/file.json", "UTF8");
For Cyrillic symbols:
ReadWithEncoding("D:/file.json", "Cp1251");
I too was getting this error ("Unexpected token END OF FILE at position 0.").
I was using same instance of com.google.gson.Gson and org.json.simple.parser.JSONParser on multiple threads.
Now I changed the code and created new instance of these on each thread, and that solved the issue.
gson = new GsonBuilder().create();
parser = new JSONParser();

how to get list from json data in java

My Json Data:
{'ID':1,'FirstName':'x','LastName':'y','Company':'x','EMail':'x','PhoneNo':'x'}
My Java Code:
public static void main(String[] args) throws IOException {
String json = getJSON().substring(getJSON().indexOf("[")+1,getJSON().indexOf("]"));
Users user = new Gson().fromJson(json, Users.class);
WriteLine("["+user.getID()+"]"+" "+user.getFirstName()+" "+user.getLastName()+" "+user.getCompany()+" "+user.getEMail()+" "+user.getPhoneNo());
}
static void WriteLine(String text){
System.out.print(text);
}
static String getJSON() throws IOException
{
URL url = new URL("http://localhost:51679/api/User");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder sBuilder = new StringBuilder();
String line;
while((line = reader.readLine()) != null){
sBuilder.append(line);
}
reader.close();
connection.disconnect();
return sBuilder.toString();
}
But my json data As these become:
{'ID':1,'FirstName':'x','LastName':'x','Company':'x','EMail':'x','PhoneNo':'x'},{'ID':2,'FirstName':'y','LastName':'y','Company':'y','EMail':'x','PhoneNo':'y'}
I have a error: Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 136
Can you help me? Sorry for my bad english :(
Read the error message carefully. That input is not valid JSON, which is exactly what the message tells you. Strings and keys must be surrounded with double quotes, not single quotes:
{"ID":1,"FirstName":"x","LastName":"y","Company":"x","EMail":"x","PhoneNo":"x"}
A simple check with a JSON validator would tell you the same. Alternately – again, as the error message conveniently tells you – you could set the reader to be lenient with JsonReader.setLenient(true), to hopefully accept malformed JSON as input.

Categories