Trying to parse JSON to String in Java - java

I'm trying to parse this stock info at:
http://www.google.com/finance/info?client=ig&q=csco
that's in JSON format to a map, essentially following this tutorial I saw using the quick-json jar but it keeps giving me an exception and I can't figure out why. Here's the code, any help is greatly appreciated
Tutorial link: https://code.google.com/p/quick-json/
public static void main(String args[]) throws IOException
{
String value="";
URL uri = new URL("http://www.google.com/finance/info?client=ig&q=csco");
BufferedReader input = new BufferedReader(new InputStreamReader(uri.openStream(), "UTF-8"));
while(input.readLine()!=null)
{
value+=input.readLine();
}
JsonParserFactory factory = JsonParserFactory.getInstance();
JSONParser parse = factory.newJsonParser();
Map jsonData =parse.parseJson(value);
System.out.println((String)jsonData.get("e"));
}
Here's the exception I get:
Exception in thread "main" com.json.exceptions.JSONParsingException: #Key-Heirarchy::root[0]/ #Key:: COMMA or ] is expected. but found :...#Position::5
at com.json.utils.JSONUtility.handleFailure(JSONUtility.java:124)
at com.json.parsers.JSONParser.stringLiteralTemplate(JSONParser.java:574)
at com.json.parsers.JSONParser.nonValidatingValueTemplate(JSONParser.java:698)
at com.json.parsers.JSONParser.jsonArrayTemplate(JSONParser.java:454)
at com.json.parsers.JSONParser.parseJson(JSONParser.java:170)
at parser.Scratch.main(Scratch.java:27)
EDIT: I also tried Map jsonData =parse.parseJson(value.substring(3) to start at [ but it still gives me an error

In addition to removing the leading // fix your loop as well. Change
while(input.readLine()!=null) // skipping odd lines
{
value+=input.readLine(); // reading even lines
}
to
String line = null;
while((line = input.readLine()) !=null)
{
value +=line;
}
or, better use a StringBuilder like
String line = null;
StringBuilder json = new StringBuilder();
while((line = input.readLine()) !=null)
{
json.append(line);
}
value = json.substring(3); // removes the leading "// "
EDIT:
I'm not familiar with your JSON parser. With the org.json. Java parser you could do it this way.
JSONArray jsonRoot = new JSONArray(value);
JSONObject quote = jsonRoot.get(0);
System.out.println ("e = " + quote.getString("e"));
But, as a workaround you could strip the [] from StringBuilder as
// removes the leading "// [" and trailing "]"
value = json.substring(4, json.length() - 1);

This json is not a valid, have two "//".
Use http://jsonlint.com/ to validate this

The response from that URL starts with //, which isn't valid JSON:
// [ { "id": "99624" ,"t" : "CSCO" ,"e" : "NASDAQ" ,"l" : "24.00" ,"l_cur" : "24.00" ,"s": "2" ,"ltt":"4:00PM EDT" ,"lt" : "Jun 25, 4:00PM EDT" ,"c" : "-0.05" ,"cp" : "-0.21" ,"ccol" : "chr" ,"el": "24.00" ,"el_cur": "24.00" ,"elt" : "Jun 25, 5:54PM EDT" ,"ec" : "0.00" ,"ecp" : "0.00" ,"eccol" : "chb" ,"div" : "0.17" ,"yld" : "2.83" } ]
According to this and this, the Google Finance API is deprecated anyway, so you may want to find something else.

Following blog has enough number of very good examples on quick-json parser
It has got other competitive parsers examples as well
http://codesnippets4all.com/html/parsers/json/quick-json.htm

Add this to your code:
String line = null;
while((line = input.readLine()) !=null)
{
value += line;
}
value = value.replace("// ", "");
You need to replace the // at the beginning to "clean" the JSON before you can parse it.

It seems you are using old quick-json parser version. Use the latest version for parsing
quick-json-1.0.2.3.jar
I could see that the json is coming as follows,
// [
{
"id": "99624"
,"t" : "CSCO"
,"e" : "NASDAQ"
,"l" : "25.41"
,"l_cur" : "25.41"
,"s": "2"
,"ltt":"3:59PM EDT"
,"lt" : "Jul 10, 3:59PM EDT"
,"c" : "+0.25"
,"cp" : "1.01"
,"ccol" : "chg"
,"el": "25.55"
,"el_cur": "25.55"
,"elt" : "Jul 10, 7:07PM EDT"
,"ec" : "+0.14"
,"ecp" : "0.55"
,"eccol" : "chg"
,"div" : "0.17"
,"yld" : "2.68"
}
]
This is not valid JSON, it should not be preceded by //
// [
remove // and just use from [ till end of the json string
i was able to parse successfully the below json string without //
[
{
"id": "99624"
,"t" : "CSCO"
,"e" : "NASDAQ"
,"l" : "25.41"
,"l_cur" : "25.41"
,"s": "2"
,"ltt":"3:59PM EDT"
,"lt" : "Jul 10, 3:59PM EDT"
,"c" : "+0.25"
,"cp" : "1.01"
,"ccol" : "chg"
,"el": "25.55"
,"el_cur": "25.55"
,"elt" : "Jul 10, 7:07PM EDT"
,"ec" : "+0.14"
,"ecp" : "0.55"
,"eccol" : "chg"
,"div" : "0.17"
,"yld" : "2.68"
}
]
Below is the output i've got with version quick-json-1.0.2.3.jar
{root=[{e=NASDAQ, c=+0.25, div=0.17, l=25.41, lt=Jul 10, 3:59PM EDT, ec=+0.14, ltt=3:59PM EDT, elt=Jul 10, 7:07PM EDT, id=99624, yld=2.68, el_cur=25.55, t=CSCO, cp=1.01, s=2, el=25.55, l_cur=25.41, eccol=chg, ccol=chg, ecp=0.55}]}

Related

Java Parsing A Json File Line To Return Part Of The Line

I am having some trouble trying to figure out how to parse a line in a json file so that it only returns part of the line as a string. I will illustrate below:
public String GetDistance(String origin, String destination) throws MalformedURLException, IOException {
//URL url = new URL("https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins" + origin + ",UK+destination=" + destination + ",UK&key=mykey");
URL url = new URL("https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=Cornwall,UK&destinations=London,UK&key=mykey");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
String line, outputString = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = reader.readLine()) != null) {
if (line.contains("distance")) {
outputString = reader.readLine().trim();
return outputString;
}
}
return outputString;
}
What this function does is create a json file in my browser using Google Maps API:
{
"destination_addresses" : [ "London, UK" ],
"origin_addresses" : [ "Cornwall, UK" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "284 mi",
"value" : 456443
},
"duration" : {
"text" : "4 hours 52 mins",
"value" : 17530
},
"status" : "OK"
}
]
}
],
"status" : "OK"
}
Currently the "outputString" returns the line: "text" : "284 mi". However, the desired output is to just return the miles, "284".
I know this is most likely a re post, however I have been searching around for a solution to this and have been unsuccessful in implementing something that works.
Any help on this would be greatly appreciated, Cheers.
You can have 2 solutions:
Parse the JSON and treat it as an object and then just return the String you're looking for.
Split the line as follows:
outputString = reader.readLine().trim();
That line above returns "text" : "284 mi"
Then you need to split the line by ::
outputString.split(":")
That should create an array with 2 Strings: "text" and "284 mi"
Then take the second String and split it by a space and take the first String:
outputString.split("\\s")
Now you have: "284
Then just return it from subindex 1 till the end, see docs:
outputString.substring(1)
And then just put it all together:
return outputString.split(":")[1].split("\\s")[0].substring(1)
I haven't tried above code but it should work.
BTW follow Java Naming Conventions
firstWordLowerCaseVariable
firstWordLowerCaseMethod()
FirstWordUpperCaseClass
ALL_WORDS_UPPER_CASE_CONSTANT
And use them consistently

Why double slashes front of JSON String

I have a JSON string from google, which i can not use it because of the double slashes in front of the JSON string, it returns JSON exception.
How can i escape them before parse?
https://www.google.com/finance/info?q=asels
// [ { "id": "530630671033488" ,"t" : "ASELS" ,"e" : "IST" ,"l" :
"13.72" ,"l_fix" : "13.72" ,"l_cur" : "TRY13.72" ,"s": "0"
,"ltt":"6:10PM GMT+3" ,"lt" : "Jan 20, 6:10PM GMT+3" ,"lt_dts" :
"2017-01-20T18:10:00Z" ,"c" : "+0.04" ,"c_fix" : "0.04" ,"cp" : "0.29"
,"cp_fix" : "0.29" ,"ccol" : "chg" ,"pcls_fix" : "13.68" } ]
You need to remove the two double slashes in beginning, then you have a regular JSON String that you can parse.
You can do it like this:
String yourJsonStringFromGoogle = ...
fixedJsonString = yourJsonStringFromGoogle.substring(2);
Here, substring(n) removes n letters from the beginning of the string.

parse json objects from a log file

I want to parse the JSON objects from my log file. For using JSON Parser my complete files has to be in JSON format which is not the case with me. Is there any way I can parse the file line by line and get the JSON objects.
Below is my log file format:
2015-10-19 11:24:35:701 INFO BrokerTcpClient:28 - Set destination
2015-10-19 11:24:35:929 DEBUG BrokerTcpClient:32 - received data: {type=data, payload={
"core" : [ {
"id" : {
"datatype" : "http://www.w3.org/2001/hk#long",
"type" : "gh",
"value" : "gh"
},
"entity" : {
"type" : "uri",
"value" : "http://fg.fg.com/ext/g/fg"
},
"Sno" : {
"type" : "literal",
"value" : "fg"
}]
2015-10-19 11:24:35:701 INFO BrokerTcpClient:28 - Set destination
2015-10-19 11:24:35:929 DEBUG BrokerTcpClient:32
"core" : [ {
"id" : {
"datatype" : "http://www.w3.org/2001/hk#long",
"type" : "gh",
"value" : "gh"
},
"entity" : {
"type" : "uri",
"value" : "http://fg.fg.com/ext/g/fg"
},
"Sno" : {
"type" : "literal",
"value" : "fg"
}]
Can any one please help how should I get my JSON objects. When I am trying to parse a single line of JSON objects throwing an exception.
Here is a solution that works for the sample log that is posted.
import java.io.*;
import com.fasterxml.jackson.databind.*;
public class JSONTest {
public static void main(String[] args) {
String logFilename = "C://Temp/sample.log";
String line, json = "";
try (BufferedReader br = new BufferedReader(new FileReader(logFilename))) {
while ((line = br.readLine()) != null) {
if (isLogLine(line)) {
if (!json.isEmpty()) {
parseJson(json);
json = "";
}
} else {
json += line;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean isLogLine(String line) {
return line.matches("^\\d{4}\\-\\d{2}\\-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}:\\d{3}.+$");
}
public static void parseJson(String json) throws Exception {
if (!json.startsWith("{") && !json.endsWith("}")) json = "{" + json + "}";
ObjectMapper om = new ObjectMapper();
System.out.println(om.readValue(fixJson(json), Object.class));
}
public static String fixJson(String json) {
return "{" + json.replace("}]", "}}]") + "}";
}
}
Notes:
the regex that identifies log line is checking for timestamp at the
begining of the line. this will not work in case the log message
spans multiple lines (for example if the message contains new line)
there is a method that attempts to "fix" the incomplete json from the log file, it may need additional logic, if there are more cases of incomplete json along the way
I used Jackson Json parser and let ObjectMapper figure out what data structure to parse into
Have you looked into logstash (https://www.elastic.co/products/logstash)? It can solve this problem and perhaps other problems you will come across when trying to parse logs.

java.lang.String cannot be converted to JSONObject

In my android application,i calling one webservice and it is returning one jsonobject.In device i getting one response like this..
"{ \"Time_Stamp\" : \"10/10/2012 4:26 PM\", \"records\" : [ { \"'Name'\" : \"'LD-00000002'\", \"'Appointment_Date_Time'\" : \"'null'\", \"'Phone'\" : \"'9909955555'\", \"'Home_Country_Address'\" : \"'null'\", \"'Occupation'\" : \"'null'\", \"'SR_Appointment_Status'\" : \"'Open'\", \"'Id'\" : \"'a0OE0000001iLynMAE'\", \"'SR_Appointment_Comment'\" : \"'testing'\", \"'ProductsOfInterest'\" : \"'null'\", \"'ActivityName'\" : \"'Sales'\", \"documentsList\" : [ ] }, { \"'Name'\" : \"'LD-00000002'\", \"'Appointment_Date_Time'\" : \"'null'\", \"'Phone'\" : \"'9909955555'\", \"'Home_Country_Address'\" : \"'null'\", \"'Occupation'\" : \"'null'\", \"'SR_Appointment_Status'\" : \"'Open'\", \"'Id'\" : \"'a0OE0000001iLynMAE'\", \"'SR_Appointment_Comment'\" : \"'testing'\", \"'ProductsOfInterest'\" : \"'null'\", \"'ActivityName'\" : \"'Sales'\", \"documentsList\" : [ { \"numberOfImages\" : 3, \"Name\" : \"new document\", \"Mandatory\" : false, \"FilePath\" : null, \"Category\" : null } ] } ]}"
i trying convert it into an object like this
JSONObject jsonObj=new JSONObject(objMngr.getResponse());
when converting it throwing one exception "java.lang.String cannot be converted to JSONObject"...below is the exact exception that it is throwig ..What is the reason and how can i solve this issue??
{ "Time_Stamp" : "10/10/2012 4:26 PM", "records" : [ { "'Name'" : "'LD-00000002'", "'Appointment_Date_Time'" : "'null'", "'Phone'" : "'9909955555'", "'Home_Country_Address'" : "'null'", "'Occupation'" : "'null'", "'SR_Appointment_Status'" : "'Open'", "'Id'" : "'a0OE0000001iLynMAE'", "'SR_Appointment_Comment'" : "'testing'", "'ProductsOfInterest'" : "'null'", "'ActivityName'" : "'Sales'", "documentsList" : [ ] }, { "'Name'" : "'LD-00000002'", "'Appointment_Date_Time'" : "'null'", "'Phone'" : "'9909955555'", "'Home_Country_Address'" : "'null'", "'Occupation'" : "'null'", "'SR_Appointment_Status'" : "'Open'", "'Id'" : "'a0OE0000001iLynMAE'", "'SR_Appointment_Comment'" : "'testing'", "'ProductsOfInterest'" : "'null'", "'ActivityName'" : "'Sales'", "documentsList" : [ { "numberOfImages" : 3, "Name" : "new document", "Mandatory" : false, "FilePath" : null, "Category" : null } ] } ]} of type java.lang.String cannot be converted to JSONObject
try
JSONObject jsonObj=new JSONObject(objMngr.getResponse().toString().replace("\\", " "));
Your jsonString seems allright. However your response type may not be string. Try it.
The problem is with already escaped inverted commas sent by the server.
First convert your response to a String then try to create a JSONObject
I think, getResponse() is already string but response isn't valid JSON.If response isn't string,you can convert string with toString() method.
It seem there are some hidden characters on your string.
Try this
return new JSONObject(json.substring(json.indexOf("{"), json.lastIndexOf("}") + 1));
Seems like you have dumped object to JSON string twice on server-side.
object --dumps()--> json string --dumps()-> one string in json
So you should remove the second dumping.
Otherwise you can unescape your string this way How to unescape a Java string literal in Java?.
The first way is better and easier i think.

Get latitude & longitude from given address name. NOT Geocoder

I have an address name and I want to get an accurate latitude & longitude for it. I know we can get this using Geocoder's getFromLocationName(address,maxresult).
The problem is, the result I get is always null - unlike the result that we get with https://maps.google.com/. This always allows me to get some results, unlike Geocoder.
I also tried another way: "http://maps.google.com/maps/api/geocode/json?address=" + address + "&sensor=false" (Here's a link!) It gives better results than geocoder, but often returns the error (java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer). It's boring.
My question is: How can we get the same latlong result we would get by searching on https://maps.google.com/ from within java code?
additional:where is the api document about using "http://maps.google.com/maps/api/geocode/json?address=" + address + "&sensor=false"
Albert, I think your concern is that you code is not working. Here goes, the code below works for me really well. I think you are missing URIUtil.encodeQuery to convert your string to a URI.
I am using gson library, download it and add it to your path.
To get the class's for your gson parsing, you need to goto jsonschema2pojo. Just fire http://maps.googleapis.com/maps/api/geocode/json?address=Sayaji+Hotel+Near+balewadi+stadium+pune&sensor=true on your browser, get the results and paste it on this site. It will generate your pojo's for you. You may need to also add a annotation.jar.
Trust me, it is easy to get working. Don't get frustrated yet.
try {
URL url = new URL(
"http://maps.googleapis.com/maps/api/geocode/json?address="
+ URIUtil.encodeQuery("Sayaji Hotel, Near balewadi stadium, pune") + "&sensor=true");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String output = "", full = "";
while ((output = br.readLine()) != null) {
System.out.println(output);
full += output;
}
PincodeVerify gson = new Gson().fromJson(full, PincodeVerify.class);
response = new IsPincodeSupportedResponse(new PincodeVerifyConcrete(
gson.getResults().get(0).getFormatted_address(),
gson.getResults().get(0).getGeometry().getLocation().getLat(),
gson.getResults().get(0).getGeometry().getLocation().getLng())) ;
try {
String address = response.getAddress();
Double latitude = response.getLatitude(), longitude = response.getLongitude();
if (address == null || address.length() <= 0) {
log.error("Address is null");
}
} catch (NullPointerException e) {
log.error("Address, latitude on longitude is null");
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
The Geocode http works, I just fired it, results below
{
"results" : [
{
"address_components" : [
{
"long_name" : "Pune",
"short_name" : "Pune",
"types" : [ "locality", "political" ]
},
{
"long_name" : "Pune",
"short_name" : "Pune",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "Maharashtra",
"short_name" : "MH",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "India",
"short_name" : "IN",
"types" : [ "country", "political" ]
}
],
"formatted_address" : "Pune, Maharashtra, India",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 18.63469650,
"lng" : 73.98948670
},
"southwest" : {
"lat" : 18.41367390,
"lng" : 73.73989109999999
}
},
"location" : {
"lat" : 18.52043030,
"lng" : 73.85674370
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 18.63469650,
"lng" : 73.98948670
},
"southwest" : {
"lat" : 18.41367390,
"lng" : 73.73989109999999
}
}
},
"types" : [ "locality", "political" ]
}
],
"status" : "OK"
}
Edit
On 'answers do not contain enough detail`
From all the research you are expecting that google map have a reference to every combination of locality, area, city. But the fact remains that google map contains geo and reverse-geo in its own context. You cannot expect it to have a combination like Sayaji Hotel, Near balewadi stadium, pune. Web google maps will locate it for you since it uses a more extensive Search rich google backend. The google api's only reverse geo address received from their own api's. To me it seems like a reasonable way to work, considering how complex our Indian address system is, 2nd cross road can be miles away from 1st Cross road :)
Hope this helps you:
public static GeoPoint getGeoPointFromAddress(String locationAddress) {
GeoPoint locationPoint = null;
String locationAddres = locationAddress.replaceAll(" ", "%20");
String str = "http://maps.googleapis.com/maps/api/geocode/json?address="
+ locationAddres + "&sensor=true";
String ss = readWebService(str);
JSONObject json;
try {
String lat, lon;
json = new JSONObject(ss);
JSONObject geoMetryObject = new JSONObject();
JSONObject locations = new JSONObject();
JSONArray jarr = json.getJSONArray("results");
int i;
for (i = 0; i < jarr.length(); i++) {
json = jarr.getJSONObject(i);
geoMetryObject = json.getJSONObject("geometry");
locations = geoMetryObject.getJSONObject("location");
lat = locations.getString("lat");
lon = locations.getString("lng");
locationPoint = Utils.getGeoPoint(Double.parseDouble(lat),
Double.parseDouble(lon));
}
} catch (Exception e) {
e.printStackTrace();
}
return locationPoint;
}
I use, in order:
- Google Geocoding API v3 (in few cases there's a problem described here)
- Geocoder (in some cases there's a problem described here).
If I don't receive results from Google Geocoding API I use the Geocoder.
As far as I noticed Google Maps is using the Google Places API for auto complete and then gets the Details for the Location from which you can get the coordinates.
https://developers.google.com/places/documentation/
https://developers.google.com/places/training/
This method should will give you the expected results.
String locationAddres = anyLocationSpec.replaceAll(" ", "%20");
URL url = new URL("https://maps.googleapis.com/maps/api/geocode/json?sensor=false&address="+locationAddres+"&language=en&key="YourKey");
try(InputStream is = url.openStream(); JsonReader rdr = Json.createReader(is)) {
JsonObject obj = rdr.readObject();
JsonArray results = obj.getJsonArray("results");
JsonObject geoMetryObject, locations;
for (JsonObject result : results.getValuesAs(JsonObject.class)) {
geoMetryObject=result.getJsonObject("geometry");
locations=geoMetryObject.getJsonObject("location");
log.info("Using Gerocode call - lat : lng value for "+ anyLocationSpec +" is - "+locations.get("lat")+" : "+locations.get("lng"));
latLng = locations.get("lat").toString() + "," +locations.get("lng").toString();
}
}

Categories

Resources