I'm getting a Json from a WebService and I want to print it as a String in my LogCat. I've tried the following:
Gson gson = new Gson();
HttpEntity getResponseEntity = httpResponse.getEntity();
InputStream is = getResponseEntity.getContent();
Reader reader = new InputStreamReader(is);
Type snsType = new TypeToken<SNSRegister>(){}.getType();
snsRegister = gson.fromJson(reader, snsType);
String jsonString = convertStreamToString(is);
snsRegister is an instance of my serializable class, i'm trying to print the JSON in my logcat by converting the InputStream object to String with the convertStreamtoString method:
static String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
but my String is always empty and I don't know why. snsRegister is not null, so that isn't the problem.
If this is really important for you to do, Gson can take a String.
I don't recommend reading the Stream twice, though you can do it with mark() and reset(). Since Gson will deserialize a String in addition to Reader, so you can just pass the String into Gson like this:
HttpEntity getResponseEntity = httpResponse.getEntity();
InputStream is = getResponseEntity.getContent();
String jsonString = convertStreamToString(is);
Log.i("MyTAG", jsonString);
Gson gson = new Gson();
Type snsType = new TypeToken<SNSRegister>() {}.getType();
snsRegister = gson.fromJson(jsonString, snsType);
I don't recommend doing this in production though, as the conversion to a String is a lot of extra work. But you can use this temporarily for debugging, obviously; the way you're currently doing it is the best way for production.
Another option would be to convert the SNSRegister object back to JSON with gson.toJson(), but that would be even slower.
Most probably your stream has been read once by GSON.
If you really, really want to read it twice you need to reset() a stream but first you have to mark() the position you want to reset to.
But all you want is to print your JSON in logcat just add toString() method to your SNSRegister class or even better user Retrofit logging mechanism.
Related
I am making a simple application where i scan the barcode of a book and fetch its title and author from Google APIs,
Now, this is the url for json(for a particular book i am scanning)
https://www.googleapis.com/books/v1/volumes?q=isbn:9788120305960
using this code to get json in a string
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"iso-8859-1"));
String line = "";
while ((line=bufferedReader.readLine())!=null)
{
response+=line;
}
bufferedReader.close();
inputStream.close();
urlConnection.disconnect();
Log.d("Info",response);
return response;
I store the result in a string and use this code to parse through
(json_response is a string)
JSONObject rootObject = new JSONObject(json_response);
JSONArray items = rootObject.getJSONArray("items");
JSONObject items_object = items.getJSONObject(0);
JSONObject volume_info = items_object.getJSONObject("volumeInfo");
book.setTitle(volume_info.getString("title"));
JSONArray authors = volume_info.getJSONArray("authors");
Log.d("Info","authors array length: "+authors.length());
String author="";
for (int i =0;i<authors.length();i++)
{
author+=authors.getString(i)+", ";
}
book.setAuthor(author);
The exception is:
Value null of type org.json.JSONObject$1 cannot be converted to JSONObject
also I used logcat to see what is contained in json_response it looks something like this
null{ "kind": "books#volumes", "totalItems": 1, "items":...
The null here is probably causing the problem, so... any insights how to deal with this???
PS: I am a student , dealing first time with json and android, code is unprofessional, please pardon :)
Having
null{ "kind": "books#volumes", "totalItems": 1, "items":...
means that the response value has not been initialised.
You should therefore initialise it to empty string.
what's up?
I have a JSON which has a Boolean as item 1 and an array of "Socio" objects as item 2 and I have to read with streaming because it's very large.
My +5.0MB JSON is kind of: {"response":true,"result":[{SOCIO OBJECT}, {SOCIO OBJECT}...]
My first code (which threw OutOfMemoryError on API 8, 9) was:
InputStream source = f.retrieveStream(params[0]);
Gson gson = new Gson();
Reader reader = new InputStreamReader(source);
Respuesta response = gson.fromJson(reader, Respuesta.class);
Socio[] socios = response.getSocio();
My new code for streaming is:
InputStream source = f.retrieveStream(params[0]);
Gson gson = new Gson();
JsonReader reader = new JsonReader(new InputStreamReader(source,"UTF-8"));
reader.skipValue(); // Because I have to skip the response... Am i doing this right??
lista = new ArrayList<Socio>();
Socio soc;
reader.beginArray();
while (reader.hasNext()) {
soc = gson.fromJson(reader, Socio.class);
lista.add(soc);
}
reader.endArray();
reader.close();
But it throws this Exception when it's almost loaded:
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was END_DOCUMENT at line 1 column 4716089
on the line which has the code: reader.beginArray();
This is where I based my streaming reading.
I've read a lot of parsing with GSON, but I can't find anything for parsing an specific array from a JSON file. I only know to do it with Android Json library but I need to use GSON. I also browsed the 10 first pages of this search on Google and I found no clear response, and I understood this SO question but it's working with objects which has names, so I cannot work with that for array.
Thanks in advance.
Regards.
Rafael.
Your streaming code is wrong, the first skipValue actually makes you skip the whole document.
Try this out:
JsonReader reader = new JsonReader(new InputStreamReader(source,"UTF-8"));
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String strName = jsonReader.nextName();
if (strName.equals("response")) {
reader.skipValue();
}
else if (strName.equals("result")) {
jsonReader.beginArray();
while (reader.hasNext()) {
soc = gson.fromJson(reader, Socio.class);
lista.add(soc);
}
jsonReader.endArray();
}
}
jsonReader.endObject();
...
I have a problem while creating jsonStringer in android. My problem is I have to post values to server using post method.So for that I have to send an array. { "name":"asdf","age":"42","HaveFiles":["abcfile","bedFile","cefFile"]} .
So how can I create a json array for haveFiles? And I don't know the no of files it may varies. So I am creating a string builder and appending the values to that.
when I print the jsonString the stringbuilder show that instead of " it shows \". But when I print the string builder it looks ["abcFile"] like this. but in jsonStringer it prints ["\""abcFile\""]. How I can resolve this issue?
Use this to create json object and pass the json object
try {
JSONObject jObj = new JSONObject(YourString);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
If you want jsonArray then
jobj.getJSONArray(TAG_NAME);
It is really simple, you can use GSON library to do it.
The usage is something like:
Gson gson = new Gson();
String jsonStr = gson.toJson(yourObj);
YourObjType yourObj2 = gson.fromJson(jsonStr, YourObjType.class);
Regarding to your situation, you can do:
Gson gson = new Gson();
String[] ss = new String[] {"abcFile", "defFile", "ghiFile"};
String jsonStr = gson.toJson(ss);
And the result of jsonStr is:
["abcFile, defFile, ghiFile"]
I have a servlet that has the following purpose:
Receive data via the URL (that is, using get). Then returns a message, based on this input, back to the caller. I am new to this stuff, but have come to learn that using json (actually, Gson) is suitable for this.
My question now is, how do I retrieve this json message? What URL do I target? The relevant lines in the servlet are:
String json = new Gson().toJson(thelist);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().println(json);
This is how I try to retrieve the json:
try{
DefaultHttpClient defaultClient = new DefaultHttpClient();
HttpGet httpGetRequest = new HttpGet("http://AnIPno:8181/sample/response?first=5&second=92866");
HttpResponse httpResponse = defaultClient.execute(httpGetRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), "UTF-8"));
String json = reader.readLine();
JSONObject jsonObject = new JSONObject(json);
} catch(Exception e){
e.printStackTrace();
}
But apparently this does not work, as I have found jsonObject has a size of 0 (it should be an array with three elements).
Previously, I had a write() instead of println() in the servlet. I'm not sure if that matters in this case. But I'm assuming I've misunderstood something about how the json object is retrieved. Is it not enough to point it towards the URL of the servlet?
Reading an InputStream whether from a File on the file system or from an HTTP request is, in most cases, the same.
What you have is correct only if your servlet wrote a single line. If the Gson object toString() method returns multiple lines, you're going to have to read multiple lines from the InputStream. I like to use the Scanner class for reading from an InputStream.
try {
DefaultHttpClient defaultClient = new DefaultHttpClient();
HttpGet httpGetRequest = new HttpGet("http://localhost:8080/cc/jsonyeah");
HttpResponse httpResponse = defaultClient.execute(httpGetRequest);
Scanner scanner = new Scanner(httpResponse.getEntity().getContent(), "UTF-8");
while(scanner.hasNextLine()) { // scanner looks ahead for an end-of-line
json += scanner.nextLine() + "\n"; // read the full line, you can append a \n
}
// do your serialization
} catch(Exception e) {
e.printStackTrace();
}
So we've done the same thing we would've done if we were reading from a file. Now the json object contains the json you received from the servlet, as a String.
For the serialization, you have a few options.
A Gson object has an overloaded method fromJson() that can take a String or a Reader, among other things.
From where we are with the code above, you can do
MyClass instance = new Gson().fromJson(json, MyClass.class);
where MyClass is the type you are trying to create. You will have to use a TypeToken for generic classes (such as a list). TypeToken is an abstract class, so generate an anonymous class and call getType()
Type type = new com.google.gson.reflect.TypeToken<List<String>>(){}.getType();
List<MyClass> list = new Gson().fromJson(json, type);
Another option is to use the overloaded method that takes a Reader directly instead of reading line by line from the InputStream:
BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), "UTF-8"));
MyClass instance = new Gson().fromJson(reader , MyClass.class);
You'll get to skip a step.
Don't forget to close your streams.
I have this function to readJsonData from a a request to a JSON String. You can use this function to retrieve the JSON, then use GSON to parse it to the object that you like. It works for my application. Hope it works for you too.
protected String readJson(HttpResponse resp)
throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(
resp.getEntity().getContent()));
StringBuffer buffer = new StringBuffer();
int read;
char[] chars = new char[1024];
while ((read = reader.read(chars)) != -1)
buffer.append(chars, 0, read);
} finally {
if (reader != null)
reader.close();
}
return buffer.toString();
}
So based on your code. I guess this should work:
String jsonData = readJson(httpResponse);
YourObject obj = new Gson().fromJson(jsonData, YourObject.class);
Before trying this, make sure your servlet prints out the JSON data that you want. I suggest using these Chrome Extensions: Postman - REST Client and JSON Formatter, to test your data from servlet. It's pretty helpful.
Here is the code I'm using inside my AsyncTask
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
request.setHeader("Accept", "application/json");
request.setHeader("Content-type", "application/json");
HttpResponse response = httpClient.execute(request);
HttpEntity responseEntity = response.getEntity();
char[] buffer = new char[(int)responseEntity.getContentLength()];
InputStream stream = responseEntity.getContent();
InputStreamReader reader = new InputStreamReader(stream);
reader.read(buffer);
stream.close();
result = new String(buffer);
return result;
This returns a string result and in my onPostExecute method I try to parse that input string:
JSONObject vehicle = new JSONObject(new String(result));
makeEdit.setText(vehicle.getString("make"));
plateEdit.setText(vehicle.getString("plate"));
modelEdit.setText(vehicle.getString("model"));
yearEdit.setText(vehicle.getString("year"));
As soon as it reaches makeEdit.setText it throws an error - no value for make. I'm still very new to android, so don't send death threats if there was some obvious error. The input text is the following JSON string:
{"GetJSONObjectResult":{"make":"Ford","model":"Focus","plate":"XXO123GP","year":2006}}
No value for x error message is pretty common when dealing with JSON. This usually resulted by overlooked code.
usually, when dong JSON, I try to see the human readable structure first. For that, I usually use JSONViewer.
In your case, the structure is something like this:
You see that make is within another object called GetJSONObjectResult. Therefore, to get it, you must first get the container object first:
JSONObject vehicle = ((JSONObject)new JSONObject(result)).getJSONObject("GetJSONObjectResult");
//a more easy to read
JSONObject container = new JSONObject(result);
JSONObject vehicle = container.getJSONObject("GetJSONObjectResult");
and finally use the object to get make:
makeEdit.setText(vehicle.getString("make"));
plateEdit.setText(vehicle.getString("plate"));
modelEdit.setText(vehicle.getString("model"));
yearEdit.setText(vehicle.getString("year"));
Your JSON Object contains itself a JSONObject. To acces to your data, you have to do like this:
vehicle.getJSONObject("GetJSONObjectResult").getString("make");