Getting data from incoming JSON in a Java servlet - java

A client is sending me a JSON file through HTTP PUT, here is the file :
{
"nomPers": "Testworking",
"prenomPers": "WorkingTest",
"loginPers": "Work",
"pwdPers": "Ing",
"active": true
},
I'm using HTTPServlet as WebService framework and the org.json library to work with Json. I'm also using Tomcat Server. As Tomcat can't create a parameter map for this HTTP verb, i've to work with JSON objects.
So I did some searching and tries but still can't make it work, here is my code :
#Override
public void doPut(HttpServletRequest request, HttpServletResponse response) {
// this parses the incoming json to a json object.
JSONObject jObj = new JSONObject(request.getParameter("jsondata"));
Iterator<String> it = jObj.keys();
while(it.hasNext())
{
String key = it.next(); // get key
Object o = jObj.get(key); // get value
System.out.println(key + " : " + o); // print the key and value
}
So i'm parsing the incoming Json to a Json object to work with, then I create an Iterator to be able to loop through this object and get and and print datas for each key/value pair.
The problem is I get a NullPointerException error.
I guess it's because of the request.getParameter("jsondata"). It seems I don't get any parameters. I guess i've to create a string from the datas i get through the request to feed the JSONObject constructor, but i don't get how to achieve this.

I think the client send JSON data to you in the body of the request, not in a parameter. So the parameter that you try to parse as JSON data will be always null. To accomplish your task, you have first of all to get the body request and then parse it as JSON. For example, you can convert the body into a String with a method like this:
public static String getBody(HttpServletRequest request) {
String body = null;
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
// throw ex;
return "";
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
}
}
}
body = stringBuilder.toString();
return body;
}
So, your method will become:
#Override
public void doPut(HttpServletRequest request, HttpServletResponse response) {
// this parses the incoming JSON from the body.
JSONObject jObj = new JSONObject(getBody(request));
Iterator<String> it = jObj.keys();
while(it.hasNext())
{
String key = it.next(); // get key
Object o = jObj.get(key); // get value
System.out.println(key + " : " + o); // print the key and value
}
...

So apparently your client was sending json string as request body due to which you were getting null while getting it from request.getParameter("jsondata").
In this case you need to pick request body data from request.getInputStream(), so your updated method should be something like this,
#Override
public void doPut(HttpServletRequest request, HttpServletResponse response) {
String jsonBody = new BufferedReader(new InputStreamReader(request.getInputStream())).lines().collect(
Collectors.joining("\n"));
if (jsonBody == null || jsonBody.trim().length() == 0) {
// return error that jsonBody is empty
}
// this parses the incoming json to a json object.
JSONObject jObj = new JSONObject(jsonBody);
Iterator<String> it = jObj.keys();
while (it.hasNext()) {
String key = it.next(); // get key
Object o = jObj.get(key); // get value
System.out.println(key + " : " + o); // print the key and value
}
}
Hope this helps.

Use below parser and JsonObject to get the data in the form of JsonObject.
These classes are available in gson-2.8.5.jar, import this jar and then use the gson libray.
JsonParser parser = new JsonParser();
JsonObject o = parser.parse(request.getParameter("jsondata"));
You can get the keySet from the JsonObject and then iterator it using Iterator.
Hope this will help you!

Related

How to remove this error -> Json parsing error: Value success at response of type java.lang.String can't be converted to JSONArray

I'm getting JSON parsing error while running my app
Below mentioned the code where I'm facing the error and the json url https://zactra.com/blackboard/teacher/auth/email/check/numankhan2754#gmail.com
MyHttpHandler myhttp = new MyHttpHandler();
String Newurl = url + "auth/email/check/"+email+"/";
// call MyServiceCall method from Myhttphandler class
String jsonstng = myhttp.MyServiceCall(Newurl);
Log.e(TAG, "Response From URL: " + jsonstng);
if (jsonstng != null) {
try {
JSONObject jsonObject = new JSONObject(jsonstng);
//getting JSON array node
JSONArray jsonArray = jsonObject.getJSONArray("response");
// Looping through all data from json
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject loopjsonObject = jsonArray.getJSONObject(i);
myid = loopjsonObject.getString("response");
// tmp hash map for single contact
HashMap<String, String> mydata = new HashMap<>();
// adding each child node to HashMap key => value
mydata.put("response", myid);
mydatalist.add(mydata);
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(StartMainActivity.this, "JSON parsing error", Toast.LENGTH_SHORT).show();
}
});
}
} else {
Log.e(TAG, "Couldn't get json from server.");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(StartMainActivity.this, "Couldn't get json from server. Check LogCat for possible errors!", Toast.LENGTH_SHORT).show();
}
});
}
Response From URL: {"response":"success"}
Json parsing error: Value success at response of type java.lang.String cannot be converted to JSONArray
{"response":"success"} is a JSONObject but you are treating it as JSONArray.
JSON array is always wrapped with []
Example : ["a", "b", "c"] OR something like array of JSONObjects . For example : [{"key":"value"}, {"key","value"}] . Many combinations are possible but most importantly it should start with []
Well
'success'
is not a json array.
an example of a json array is the following
"cars":[ "Ford", "BMW", "Fiat" ]
that is why it cannot be parsed.
the upper example 'cars' array has String values. so String Objects.
In your example you have after the jsonArray a for loop for the jsonArray
for (int i = 0; i < jsonArray.length(); i++)
there you say that you expect JSONObject
so the format that you are waiting is
{"response":[ {"response":"success"},{"response":"success"},{"response":"success"} ]}
which i believe is not the one you finally want :P.
You also create a new HashMap<>() inside the loop. (read about HashMap because your implementation does not support the same key usage ex. cannot have a hashmap with two string objects with same key 'response')
do not make only checks for null checks, do also checks if the string is blank.
First, define the correct format of the response from your service, then the correct implementation for you to capture your data and search the web so that the response to be parsed to an object by the use of a library like jackson.
Regards!
Ps if you want to handle this response,
then
String jsonstng = "{\"response\":\"success\"}";//your service response
String responseValue = "fail";
if (jsonstng != null) {
try {
JSONObject jsonObject = new JSONObject(jsonstng);
if (jsonObject.length() > 0 && jsonObject.has("response")) {
responseValue = jsonObject.getString("response");
}
} catch (final JSONException e) {
//log and handle error
}
}
System.out.println(responseValue);
may be enough

Getting a Json information

I am coding in Java and I'm using the minimal-json library. I am trying to get some information from a json text (idk if it's an array).
I'm trying to access the "game" value inside "stream", but I always get a crash by nullpointer or a parseexception.
Here is the json string I'm trying to get (From the Twitch Api):
{"_links":{"self":"https://api.twitch.tv/kraken/streams/hackerc0w","channel":"https://api.twitch.tv/kraken/channels/hackerc0w"},"stream":{"_id":13817896816,"game":"Programming","viewers":13,"created_at":"2015-04-01T13:54:54Z","video_height":1080,"average_fps":59.9235368156,"_links":{"self":"https://api.twitch.tv/kraken/streams/hackerc0w"},"preview":{"small":"http://static-cdn.jtvnw.net/previews-ttv/live_user_hackerc0w-80x45.jpg","medium":"http://static-cdn.jtvnw.net/previews-ttv/live_user_hackerc0w-320x180.jpg","large":"http://static-cdn.jtvnw.net/previews-ttv/live_user_hackerc0w-640x360.jpg","template":"http://static-cdn.jtvnw.net/previews-ttv/live_user_hackerc0w-{width}x{height}.jpg"},"channel":{"_links":{"self":"https://api.twitch.tv/kraken/channels/hackerc0w","follows":"https://api.twitch.tv/kraken/channels/hackerc0w/follows","commercial":"https://api.twitch.tv/kraken/channels/hackerc0w/commercial","stream_key":"https://api.twitch.tv/kraken/channels/hackerc0w/stream_key","chat":"https://api.twitch.tv/kraken/chat/hackerc0w","features":"https://api.twitch.tv/kraken/channels/hackerc0w/features","subscriptions":"https://api.twitch.tv/kraken/channels/hackerc0w/subscriptions","editors":"https://api.twitch.tv/kraken/channels/hackerc0w/editors","videos":"https://api.twitch.tv/kraken/channels/hackerc0w/videos","teams":"https://api.twitch.tv/kraken/channels/hackerc0w/teams"},"background":null,"banner":null,"broadcaster_language":"en","display_name":"hackerc0w","game":"Programming","logo":null,"mature":false,"status":"Coding a Chatbot in C","partner":false,"url":"http://www.twitch.tv/hackerc0w","video_banner":null,"_id":41236491,"name":"hackerc0w","created_at":"2013-03-11T17:08:22Z","updated_at":"2015-04-01T17:17:44Z","delay":0,"followers":28,"profile_banner":null,"profile_banner_background_color":null,"views":2948,"language":"de"}}}
The way I got if the livestreamer was live was like this:
public static boolean isStreamLive(String channel) {
try {
URL url = new URL(TWITCH_STREAM.replace("$c$", channel)) );
URLConnection conn = url.openConnection();
BufferedReader br = new BufferedReader( new InputStreamReader( conn.getInputStream() ));
String inputLine = br.readLine();
br.close();
JsonObject jsonObj = JsonObject.readFrom(inputLine);
return ( jsonObj.get("stream").isNull() )?false:true;
} catch (IOException e) {
return false;
}
}
And I mostly tried to copy the method above. But I have been checking the documentation of the library to know and I have been trying a lot of things.
The last was this:
public static String checkGame(String channel) {
if (!isStreamLive(channel)) return "El Estreamer esta Offline!";
try {
URL url = new URL( insertChannel(TWITCH_STREAM, channel) );
URLConnection conn = url.openConnection();
BufferedReader br = new BufferedReader( new InputStreamReader( conn.getInputStream() ));
String inputLine = br.readLine();
br.close();
JsonObject object = JsonObject.readFrom(inputLine);
JsonValue value = object.get("stream").asObject();
String msg = value.valueOf("status").toString();
return msg;
} catch (IOException e) {
return "Algo raro paso :/ error: 3";
}
return channel;
}
You've got two main problems with the code you've shown.
The first problem that you're having is that you're trying to get the status out of the wrong nested object. You're getting the stream object from the original json and then trying to get the value of the status key from that, but in the json you've posted status is part of a nested channel object.
The structure of the json object is like so:
{
"_links": { ... },
"stream": {
...
"channel":{
"_links": { ... },
...
"status":"Coding a Chatbot in C",
...
}
}
}
... so you can't get status directly from stream, you need to get channel from stream and get the status from that.
The second problem is that you're trying to use valueOf() to pull a value out of a JsonObject. valueOf() is a static method which creates a new object based on the supplied input, so it doesn't actually use data in the object you call it on.
Calling value.valueOf("status") will completely ignore data in value and create a new JsonObject containing the string "status".
If you want to get the value of a nested object, you need to drill down to it with a series of successive get("objName").asObject() calls, and then call .get("key") to obtain the value you want:
// hardcoded for example, actually would be read from BufferedReader
String inputLine = "{\"_links\":{\"self\":\"https://api.twitch.tv/kraken/streams/hackerc0w\",\"channel\":\"https://api.twitch.tv/kraken/channels/hackerc0w\"},\"stream\":{\"_id\":13817896816,\"game\":\"Programming\",\"viewers\":13,\"created_at\":\"2015-04-01T13:54:54Z\",\"video_height\":1080,\"average_fps\":59.9235368156,\"_links\":{\"self\":\"https://api.twitch.tv/kraken/streams/hackerc0w\"},\"preview\":{\"small\":\"http://static-cdn.jtvnw.net/previews-ttv/live_user_hackerc0w-80x45.jpg\",\"medium\":\"http://static-cdn.jtvnw.net/previews-ttv/live_user_hackerc0w-320x180.jpg\",\"large\":\"http://static-cdn.jtvnw.net/previews-ttv/live_user_hackerc0w-640x360.jpg\",\"template\":\"http://static-cdn.jtvnw.net/previews-ttv/live_user_hackerc0w-{width}x{height}.jpg\"},\"channel\":{\"_links\":{\"self\":\"https://api.twitch.tv/kraken/channels/hackerc0w\",\"follows\":\"https://api.twitch.tv/kraken/channels/hackerc0w/follows\",\"commercial\":\"https://api.twitch.tv/kraken/channels/hackerc0w/commercial\",\"stream_key\":\"https://api.twitch.tv/kraken/channels/hackerc0w/stream_key\",\"chat\":\"https://api.twitch.tv/kraken/chat/hackerc0w\",\"features\":\"https://api.twitch.tv/kraken/channels/hackerc0w/features\",\"subscriptions\":\"https://api.twitch.tv/kraken/channels/hackerc0w/subscriptions\",\"editors\":\"https://api.twitch.tv/kraken/channels/hackerc0w/editors\",\"videos\":\"https://api.twitch.tv/kraken/channels/hackerc0w/videos\",\"teams\":\"https://api.twitch.tv/kraken/channels/hackerc0w/teams\"},\"background\":null,\"banner\":null,\"broadcaster_language\":\"en\",\"display_name\":\"hackerc0w\",\"game\":\"Programming\",\"logo\":null,\"mature\":false,\"status\":\"Coding a Chatbot in C\",\"partner\":false,\"url\":\"http://www.twitch.tv/hackerc0w\",\"video_banner\":null,\"_id\":41236491,\"name\":\"hackerc0w\",\"created_at\":\"2013-03-11T17:08:22Z\",\"updated_at\":\"2015-04-01T17:17:44Z\",\"delay\":0,\"followers\":28,\"profile_banner\":null,\"profile_banner_background_color\":null,\"views\":2948,\"language\":\"de\"}}}";
JsonObject object = JsonObject.readFrom(inputLine); // parse json into object
JsonObject stream = object.get("stream").asObject(); // get "stream" sub-object
JsonObject channel = stream.get("channel").asObject(); // get "channel" sub-object
JsonValue status = channel.get("status"); // get the value of "status"
String msg = status.asString();
System.out.println(msg); // Coding a Chatbot in C

HTTPResponse as JSON in Java

I was trying to get an JSONObject from a HTTP response.
try
{
GetMethod postMethod = new GetMethod();
postMethod.setURI(new URI(url, true));
postMethod.setRequestHeader("Accept", "application/json");
httpClient.executeMethod(postMethod);
String resp=postMethod.getResponseBodyAsString();
org.json.JSONTokener tokener = new org.json.JSONTokener(resp);
finalResult = new org.json.JSONArray(tokener);
return finalResult;
}
But I got a runtime warning as
Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.
Should I get the response as stream as suggested by the JVM ? If so, how could I parse the JSON from it ?
Has your server been set up to inform clients how big its responses are? If not, your server is streaming the data, and it's technically impossible to tell how much buffer space is required to deal with the response, warranting a warning that something potentially dangerous is going on.
if you want to send jsonObjects from server suppose (tomcat server)
For server side-
creating jsonobjects-
I have Called toJson() for creating jsonobjects this is the implementation-
final JSONObject arr = new JSONObject();
for (int i = 0; i < contactStatus.size(); i++) {
ContactStatus contactObject = contactStatus.get(i);
try {
arr.put(String.valueOf(i), toJson(value1, value2,, value3));
} catch (JSONException e) {
catch block e.printStackTrace();
}
}
//Here we serialize the stream to a String.
final String output = arr.toString();
response.setContentLength(output.length());
out.print(output);//out is object of servlet output stream.
public static Object toJsonForContact(String value1, boolean value2, double value3) throws JSONException {
JSONObject contactObject = new JSONObject();
contactObject.put("id", id);
contactObject.put("status", value1);
contactObject.put("distance", value2);
contactObject.put("relation", value3);
return contactObject;
}
so your jsonobjects are ready for sending we write these objects to ServletoutputStream.
in client side-
while ((ReadResponses = in.readLine()) != null) {
Constants.Response_From_server = ReadResponses;
if (Constants.Response_From_server.startsWith("{")) {
ListOfContactStatus = new ArrayList<ContactStatus>();
ContactStatus contactStatusObject;
try {
JSONObject json = new JSONObject(Constants.Response_From_server);
for (int i = 0; i < json.length(); i++) {
contactStatusObject = new ContactStatus();
JSONObject json1 = json.getJSONObject(String.valueOf(i));
System.out.println("" + json1.getString("id"));
System.out.println("" + json1.getBoolean("status"));
System.out.println("" + json1.getDouble("distance"));
contactStatusObject.setId(json1.getString("id"));
contactStatusObject.setStatus(json1.getBoolean("status"));
contactStatusObject.setDistance((float) json1.getDouble("distance"));
ListOfContactStatus.add(contactStatusObject);
System.out.println("HTTPTransport:sendMessage Size of ListOfContactStatus" + ListOfContactStatus.size());
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
You can easily generate JSonObject usin Java EE 7. The sample code.
JsonReader reader = Json.createReader(new URI(url, true));
JsonObject jsonObject=reader.readObject();
For details information go through to the link.
http://docs.oracle.com/javaee/7/tutorial/doc/jsonp003.htm#BABHAHIA

java.lang.ClassCastException: java.lang.String JSON Tokener android

The following is my code. It works fine on the emulator. But when I run it on my android device, it crashes with java.lang.ClassCastException: java.lang.String at the line marked below. I can't find the place where the casting has gone wrong. Any help would be greatly appreciated! :)
public static MatrixCursor getRespAsCursor(String query) {
String url = (String)(API_URL + "?api_key=" + API_KEY + "&" + query);
System.out.println(url);
String resp = (String)getAPIResp(url);
JSONObject reply;
MatrixCursor emptyCursor = new MatrixCursor(new String[0]);
try {
reply = (JSONObject) new JSONTokener(resp).nextValue();//CRASHES HERE
String statusCode = (String)reply.getString("statusCode");
if(!statusCode.equals("200")) {
return emptyCursor;
}
int count = Integer.parseInt(reply.getString("count"));
if(count < 1) {
return emptyCursor;
}
JSONArray data = reply.getJSONArray("data");
//Get keys in String[] format
Iterator<String> keys = data.optJSONObject(0).keys();
List<String> copy = new ArrayList<String>();
//Add "_id" as adapters need it for traversal
copy.add("_id");
//copy rest of the keys
while (keys.hasNext())
copy.add(keys.next());
String[] sKeys = new String[copy.size()];
copy.toArray(sKeys);
int len = data.length();
//Create Cursor with JSON keys as columns
MatrixCursor resultCursor = new MatrixCursor(sKeys, len);
//Add rows to Cursor
for(int i = 0; i < len; i++) {
JSONObject d = data.optJSONObject(i);
List<Object> values = new ArrayList<Object>();
for(String key: copy) {
if(key.equals("_id")) {
values.add(Integer.toString(i));
}
else {
values.add(d.opt(key));
}
}
resultCursor.addRow(values);
}
return resultCursor;
}
catch(JSONException e) {
return emptyCursor;
}
}
You've already shown the place the casting goes wrong - it's here:
reply = (JSONObject) new JSONTokener(resp).nextValue();
nextValue() is returning a String, and you're casting it to JSONObject.
I suspect the JSON isn't as you expect it to be - it's not a statusCode = "value" pair; it's just the value.
You should check the JSON that you're returning, and either change to cast to a string, or if you want to be able to handle both forms of JSON, check the result with instanceof before casting:
Object reply = new JSONTokener(resp).nextValue();
if (reply instanceof String) {
...
} else if (reply instanceof JSONObject) {
...
}
You might wanna have a look at JSONTokener javadoc
The doc says nextValue()
Get the next value. The value can be a Boolean, Double, Integer,
JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
You are probably getting the ClassCastException as your line of code
reply = (JSONObject) new JSONTokener(resp).nextValue();//CRASHES HERE
does not return JSONObject.
You might want to check instance type of the returned object before typecasting it.
For example,
Object obj = new JSONTokener(resp).nextValue();
if(obj instanceof JSONObject){
reply = (JSONObject)obj;
} else {
//Handle otherwise,
}
reply = (JSONObject) new JSONTokener(resp).nextValue();//CRASHES HERE
If you are getting a ClassCastException is because the Object returned by nextValue() is not a JSONObject (probably a String instance)

how to get a value by key from an json (or xml) string?

In the android app I get an xml or json string returned, However, I cant seem to figure out any way on how to get an value from the string in any way by entering an key.
In PHP you just use something like $myArray['parent']['child'] but I have no clue on how this works in java.
Any idea's would be greatly appreciated! (an example for both XML and JSON even more ;) )
Here's what I would do:
locate an XML/JSON library (there's tons) (google-gson for json)
read the documentation to find a parse method ((new JsonParser()).parse(text))
read the documentation to find out what the return value is (JsonElement)
decide what you want to do with the parsed data (myJsonObj.get(...))
write the code
public class parsingjsontest2 extends Activity {
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(main);
String str = connect("http://rentopoly.com/ajax.php?query=Bo"));
System.out.println("String::"+str);
}
}
private String connect(String url)
{
// Create the httpclient
HttpClient httpclient = new DefaultHttpClient();
// Prepare a request object
HttpGet httpget = new HttpGet(url);
// Execute the request
HttpResponse response;
// return string
String returnString = null;
try {
// Open the webpage.
response = httpclient.execute(httpget);
if(response.getStatusLine().getStatusCode() == 200){
// Connection was established. Get the content.
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
// to worry about connection release
if (entity != null) {
// A Simple JSON Response Read
InputStream instream = entity.getContent();
// Load the requested page converted to a string into a JSONObject.
JSONObject myAwway = new JSONObject(convertStreamToString(instream));
// Get the query value'
String query = myAwway.getString("query");
**// Make array of the suggestions
JSONArray suggestions = myAwway.getJSONArray("suggestions");
// Build the return string.
returnString = "Found: " + suggestions.length() + " locations for " + query;
for (int i = 0; i < suggestions.length(); i++) {
returnString += "\n\t" + suggestions.getString(i);
}
// Cose the stream.
instream.close();
}
}
else {
// code here for a response othet than 200. A response 200 means the webpage was ok
// Other codes include 404 - not found, 301 - redirect etc...
// Display the response line.
returnString = "Unable to load page - " + response.getStatusLine();
}
}
catch (IOException ex) {
// thrown by line 80 - getContent();
// Connection was not established
returnString = "Connection failed; " + ex.getMessage();
}
catch (JSONException ex){
// JSON errors
returnString = "JSON failed; " + ex.getMessage();
}
return returnString;
}
private static String convertStreamToString(InputStream is) {
/*
* To convert the InputStream to String we use the BufferedReader.readLine()
* method. We iterate until the BufferedReader return null which means
* there's no more data to read. Each line will appended to a StringBuilder
* and returned as String.
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
As you didn't specify what kind of xml you are trying to read, I'm answering based on what I know.
In Android, if you were talking about the layout and strings.xml files, you use a dot (.) operator, like R.string.appname.
Please post more details about your specific problem, if this is not what you were looking for.

Categories

Resources