I am struggling with some JSON parsing (with Google's GSON library).
Here is my minimal code example:
Gson gson = new Gson();
String line = "{\"method\":\"GET\",\"status\":\"200 - OK\"}";
AnalysisReport report = gson.fromJson(line, AnalysisReport.class); //this works
JsonReader reader = new JsonReader(new StringReader(line));
reader.setLenient(true); //accept malformed input
while (reader.hasNext()) {
report = gson.fromJson(reader, AnalysisReport.class); //this doesn't work
}
reader.close();
I get the following exception: (the string is 36 chars long)
Expected BEGIN_OBJECT but was END_DOCUMENT at line 1 column 37
My ReportAnalysis class looks like this:
public class AnalysisReport {
#SerializedName("method")
private String method;
#SerializedName("status")
private String status;
AnalysisReport(){
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getStatus() {
return status;
}
}
I do not see why my code is not working. I followed the exmaple from Google
= = = EDIT = = =
The reader.hasNext() method always returns true. It seams that the method does not consume any tokens from the stream. But somehow still moves to the end of the stream and failes reading objects.
The problem was indeed the loop (facepalm). This works perfectly fine:
JsonReader reader = new JsonReader(new StringReader(line));
reader.setLenient(true); //accept malformed input
report = gson.fromJson(reader, AnalysisReport.class);
Thanks
I just removed loop and its working fine .
String line = "{\"method\":\"GET\",\"status\":\"200 - OK\"}";
AnalysisReport report = new AnalysisReport();
Gson gson = new GsonBuilder().create();
JsonReader reader = new JsonReader(new StringReader(line));
reader.setLenient(true); //accept malformed input
report = gson.fromJson(line, AnalysisReport.class); //this doesn't work
reader.close();
System.out.println(report.toString());
Related
I am new to JSON data format and java programming language; hence, I cannot find a valid answer. Actually, I have to read this API https://www.doviz.com/api/v1/currencies/all/latest, and obtain some important contents from this API. Hence, I decided to use google's GSON class, and I wrote this code.
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Scanner;
import com.google.gson.Gson;
public class Main {
public static void main( String[] args ) throws Exception{
String line = "";
String jsonString = "";
URL myUrl = new URL("https://www.doviz.com/api/v1/currencies/all/latest");
BufferedReader reader = new BufferedReader( new InputStreamReader(myUrl.openStream()) );
while( (line = reader.readLine()) != null ){
System.out.println(line);
jsonString += line;
}
reader.close();
jsonString = jsonString.substring(1, jsonString.length() - 1);
Gson gson = new Gson();
Currency json = gson.fromJson(jsonString, Currency.class);
}
}
public class Currency {
public double getSelling(){
return selling;
}
public double getBuyiing(){
return buying;
}
public String getCode(){
return code;
}
private double selling;
private transient long update_date;
private transient int currency;
private double buying;
private transient double change_rate;
private transient String name;
private transient String full_name;
private String code;
}
This code causes error, and as far as I guess, the main reason for the errors is that I do not put backslash in son string like this: "{\"brand\":\"Jeep\", \"doors\": 3}"
What I am wondering is why we need to put these backslash ?
There are 2 things to mention.
The " character is the String delimiter. A String starts at a " mark, and ends at the next one. (When initializing it explicitly, not using other variables) If you want to include " character in your String, you need to escape it like \" - so Java knows that it is not the end of the String, just a part of the content.
In JSON you should use single quotes ' - many libraries accept double quotes also, but it is not correct actually, and if any api complains about them, the API is right.
So your payload should look like {'brand': 'Jeep', 'doors': 3} I mean the other way around of course.
When you receive a JSON output from the api, you can directly use the output and can deserialize it. You don't need to have escape characters in the json string. They are required when you define the json string yourself. For example String s = "{\"current_user_url\"}"; because it is the compiler which forces you to escape it. But the json output you are getting as an API response is in a variable and if type of variable and the content you are assigning to it are same then compiler can't compain about that.
Now, I have used your code only but used the Github public API and I am able to deserialize the output json without any operation on the output string whatsoever like escaping the "" or changing "" to ''.
class Github {
private String current_user_url;
private String authorizations_url;
public String getCurrent_user_url() {
return current_user_url;
}
public void setCurrent_user_url(String current_user_url) {
this.current_user_url = current_user_url;
}
public String getAuthorizations_url() {
return authorizations_url;
}
public void setAuthorizations_url(String authorizations_url) {
this.authorizations_url = authorizations_url;
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
String line = "";
String jsonString = "";
URL myUrl = new URL("https://api.github.com");
BufferedReader reader = new BufferedReader( new InputStreamReader(myUrl.openStream()) );
while( (line = reader.readLine()) != null ){
//System.out.println(line);
jsonString += line;
}
reader.close();
System.out.println(jsonString);
Gson g = new Gson();
Github gi = g.fromJson(jsonString, Github.class);
System.out.println(gi.getAuthorizations_url());
System.out.println(gi.getCurrent_user_url());
}
I also defined the json string myself and desrialized it using GSON. In this case while defining the json string I needed to escape the double quotes as shown below:
String s = "{\"current_user_url\":\"http://test.com/user\"}";
Gson g = new Gson();
Github gi = g.fromJson(s, Github.class);
System.out.println(gi.getCurrent_user_url());
Also, JSON strings should contain double quotes only and if you use single quotes then you may get an error.
I've below json value in my StringBuilder variable, I want to parse all id key value and store it again in StringBuilder.
{"status":"success","id":"1"}
{"status":"success","id":"2"}
{"status":"success","id":"3"}
{"status":"success","id":"4"}
{"status":"success","id":"5"}
{"status":"success","id":"6"}
Expected output:
1
2
3
4
5
6
How can I parse these value in java?
I tried below option but it doesn't help:
StringBuilder str = new StringBuilder();
str.append(jsonStringValue);
JSONObject jObj = new JSONObject(str);
jObj.getString("id");
Using JSONTokener
JSONTokener t = new JSONTokener(str.toString());
while (t.more()) {
JSONObject o2 = (JSONObject) t.nextValue();
System.out.println(o2.getString("id"));
}
But I'm getting below error message:
org.json.JSONException: Missing value at character 128
If you're using org.json, You can use JSONTokener.
Here's example shows how it works.
public static void main(String args[]) throws JSONException {
String str1 = "{\"strValue\":\"string\"}\n{\"intValue\":1}";
JSONTokener t = new JSONTokener(str1);
JSONObject o1 = (JSONObject) t.nextValue();
JSONObject o2 = (JSONObject) t.nextValue();
System.out.println(o1.getString("strValue"));
System.out.println(o2.getLong("intValue"));
System.out.println(t.more()); // Check if there's more token. can be used to process with loop.
}
Or if you can change input string, you can put those object into Json array.
[
{"status":"success","id":"1"},
{"status":"success","id":"2"},
{"status":"success","id":"3"},
{"status":"success","id":"4"},
{"status":"success","id":"5"},
{"status":"success","id":"6"}
]
In that case you can use org.json.JSONArray to handle it.
You can use regexps like this
public class Test {
public static void main(String[] args) {
StringBuilder inputBuf = prepareStringBuilder();
StringBuilder outputBuf = new StringBuilder();
Pattern pattern = Pattern.compile(":\"(\\d+)\"");
Matcher matcher = pattern.matcher(inputBuf);
while (matcher.find()) {
String group = matcher.group(1);
outputBuf.append(group);
}
System.out.println(outputBuf);
}
private static StringBuilder prepareStringBuilder() {
StringBuilder buf = new StringBuilder();
buf.append("{\"status\":\"success\",\"id\":\"1\"}");
buf.append("{\"status\":\"success\",\"id\":\"2\"}");
buf.append("{\"status\":\"success\",\"id\":\"3\"}");
buf.append("{\"status\":\"success\",\"id\":\"4\"}");
buf.append("{\"status\":\"success\",\"id\":\"5\"}");
buf.append("{\"status\":\"success\",\"id\":\"6\"}");
return buf;
}
}
I'm simply trying to create JSON object like that:
JSONObject jsonObject = new JSONObject(new JsonUtility().execute(UrlUtility.url + "/" + lessonUrl).get());
Error occurs here ^ with message received in catch block:
org.json.JSONException: End of input at character 0 of
JsonUtility class as follows (I belive problem lies not there but still):
private class JsonUtility extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String result = "";
try {
InputStream inputStream = new URL(params[0]).openStream();
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"), 8);
StringBuilder sBuilder = new StringBuilder();
// Reading Json into StringBuilder
String line = null;
while ((line = bReader.readLine()) != null) {
sBuilder.append(line + "\n");
}
inputStream.close();
// Converting Json from StringBuilder to String
result = sBuilder.toString();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
You see that response is concatenated from strings (due to application logic). The final string is: http://itvdn-api.azurewebsites.net/api/courses/test-driven-development/tdd-introduction. As you see when I redirect to that link it gives JSON response.
I have tried to evaluate this UrlUtility.url and received that:
That weird ending of char array confuses me. Perhabs its the problem. Tried to replace those characters using String.replaceAll("'\u0000'0", "" ). Didnt work.
Please help. Will appreciate any ideas. Thanks.
EDIT:
Also, when I hardcode link as:
JSONObject jsonObject = new JSONObject(new JsonUtility().execute("http://itvdn-api.azurewebsites.net/api/courses/test-driven-development/tdd-introduction").get());
It works!
EDIT #2 # ρяσѕρєя K
result = sBuilder.toString(); is empty - "" since it can't parse that concatenated string.
Note: I've been using the same parser with different links in this application e.g. http://itvdn-api.azurewebsites.net/api/courses and that was working fine (but there was no concatenation with link)
/**
* Convert InputStream into String
* #param is
* #return
* #throws IOException Throws an IO Exception if input stream cannot be read
*/
public static String stringFromInputStream(InputStream is) throws IOException {
if (is != null) {
byte[] bytes = new byte[1024];
StringBuilder x = new StringBuilder();
int numRead = 0;
while ((numRead = is.read(bytes)) >= 0)
x.append(new String(bytes, 0, numRead));
return x.toString();
}
else {
return "";
}
}
Use this method for reading the inputstream and get the string.
I'm trying to parse the following url:
http://api.crossref.org/works?rows=2
When I parse it through Gson, I got some records but somehow some others stay null.
Here is my code:
BufferedReader in = new BufferedReader(new InputStreamReader(url_tdm.openStream(), "UTF-8"));
StringBuffer buffer = new StringBuffer();
int read;
char[] chars = new char[1024];
while ((read = in.read(chars)) != -1)
buffer.append(chars, 0, read);
String jsonLine = buffer.toString();
JsonReader reader = new JsonReader(new StringReader(jsonLine));
reader.setLenient(true); // this is for Malformed json
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES).create();
Crossref answer = gson.fromJson(reader, Crossref.class );
List<Items> ao = answer.message.items;
public class Crossref {
public Message message;}
public class Message {
public List<Items> items;}
public class Items {
public List<String> containerTitle;
public List<String> ISSN;
public String publisher;
public List<String> title;
public String DOI;
public String type;}
So as a result of my code above, I can get container-title, publisher and title values. But ISSN and DOIs are null.
I used a FieldNamingPolicy because "container-title" contains a dash and I could not name my field like that in java (so I wrote it as camel case containerTitle).
I am not sure if this affects DOI and ISSN records which are upper case or is it something totally different?
The best way to fix something like this is to use a gson custom deserializer
I suggest that you read this other question to see a good exemple: How do I write a custom JSON deserializer for Gson?
And you can find some other greats exemples and explanations here
I need to parse json object for this url
I have used following code
private void parse(String url2) throws MalformedURLException, IOException,JSONException {
// TODO Auto-generated method stub
InputStream is = new URL(url2).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
JSONArray nameArray = json.names();
JSONArray valArray = json.toJSONArray(nameArray);
for(int i=0;i<valArray.length();i++)
{
String p = nameArray.getString(i) + "," + valArray.getString(i);
Log.i("p",p);
}
} finally {
is.close();
}
}
private String readAll(BufferedReader rd) throws IOException {
// TODO Auto-generated method stub
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}}
But I am getting the source of the file in the jsonText String.And as it does not start with a '{' i am getting following error in the log :
org.json.JSONException: A JSONObject text must begin with '{' at character 1>
Looks to me like the issue is with the page you have created to return the response. Is there a particular reason you are using an HTML page with frames? If you browse the page loaded in the frame (http://88.198.1.116:9080/parentconnect/services/student/getStudentDetails?studentid=1&schoolid=1) you will see that the source has the JSON string you are after.
Why are you not browsing to this URL instead of the HTML page?
Based on the fact that the string does not start with a '{' character I would say the json you have is actually invalid and malformed json. Take a look here and here.
I would say your options are to see if you can get the malformed json fixed on the server side, or else on the client do some checks to see if it's malformed and try to fix it before passing the string to the jsonObject parsers.