Android: Exception when converting a String into a JSONObject - java

I get the following Error when I try to convert a JSON String into a JSONObject.
Value 48.466667|9.883333 at location of type java.lang.String
cannot be converted to JSONObject
The String is valid JSON, I tested it with http://jsonlint.com/
Example:
{"name":"An der Decke","location":"48.412583|10.0385","type":"Virtual","size":null,"status":"Available","difficulty":1,"rating":null,"terrain":1}
The code that produces the exception looks like that:
jsonObject = new JSONObject(result);
jsonArray = new JSONArray();
Iterator<String> iter = jsonObject.keys();
while (iter.hasNext()) {
String key = iter.next();
try {
JSONObject value = (JSONObject) jsonObject.get(key); <---- Exception
jsonArray.put(value);
} catch (JSONException e) {
// Something went wrong!
}
}
Is the pipe | symbol not a valid character in Java JSON?
EDIT:
The thing is, it works fine if the JSON String doesn't include the "location":"48.412583|10.0385" part...

You seem to misunderstand how the org.json library works.
As explained on the JSON homepage, a JSON value can be a string, number, object, array, true/false or null. The library maps these value types to String, Number subclasses, JSONArray, JSONObject, Boolean or null.
Not everything in that library is a JSONObject. In fact, a JSONObject is specifically used to represent a name/value pair object. JSONObject.get() can potentially return any of the aforementioned value types, that's why it needs to fall back to the greatest common denominator type: Object (and not JSONObject). Thus, casting everything to a JSONObject won't work.
It's your responsibility to ensure that you're casting to the correct type using your knowledge of the incoming data structure. This seems to be a problem in your case: your JSON string contains strings (for name, location, type and status), integers (for difficulty and terrain) and nulls (for size). What exactly are you trying to do with these?

If your goal is just to get a JSONArray of all your JSON string values, there's a much simpler way to do it.
JSONObject jsonObject = new JSONObject(result);
JSONArray jsonArray = jsonObject.toJSONArray(jsonObject.names());
System.out.println(jsonArray); // prints:
// [1,"Available","48.412583|10.0385","An der Decke",1,null,"Virtual",null]
With that aside, you were wrong to assume that every value encapsulated within JSON would be a JSON object itself. In fact, in your case none of them are. The correct types of all the values in your JSON are
// String
System.out.println(jsonObject.getString("name")); // An der Decke
System.out.println(jsonObject.getString("location")); // 48.412583|10.0385
System.out.println(jsonObject.getString("type")); // Virtual
System.out.println(jsonObject.getString("status")); // Available
// Null
System.out.println(jsonObject.isNull("size")); // true
System.out.println(jsonObject.isNull("rating")); // true
// Integer
System.out.println(jsonObject.getInt("terrain")); // 1
System.out.println(jsonObject.getInt("difficulty")); // 1
On the other hand, if your name was an embedded JSON object consisting of first, middle and last names, your JSON string (ignoring the rest of the keys for brevity) would have looked like
{"name": {"fname" : "An", "mname" : "der", "lname" : "Decke"}}
Now, we can put getJSONObject() to use because we really do have an embedded JSON object.
JSONObject jsonObj = new JSONObject("{\"name\":
{\"fname\" : \"An\", \"mname\" : \"der\", \"lname\" : \"Decke\"}}");
// get embedded "name" JSONObject
JSONObject name = jsonObj.getJSONObject("name");
System.out.println(name.getString("fname") + " "
+ name.getString("mname") + " "
+ name.getString("lname")); // An der Decke

The get() method of JSONObject returns a result of type Object. In this case, it seems it is a String. It's as if you were doing
JSONObject value = (JSONObject) new String("asdasdsa");
which obviously makes no sense as they are incompatible types.
Instead, retrieve the value, create a JSONObject from it and add it to the JSONArray.

Related

How to handle the case when field is not present in Object Java?

I have an object something like this in my database and now my requirement is to find the value of particular field such as name and if present return true,
{
"_id" : "123",
"name" : "Team"
}
but in some case the field name itself doesn't exist. Sample can be something like this:
{
"id":1234
}
In this case I need to return false.
How can I validate if name field exist in particular object?
I was trying to use StringUtils method something like this
StringUtils.isBlank(obj.getName); But its throwing It is throwing java.lang.NullPointerException .
You can use Json schema validator. If your json will be in specific format. Please have a look at Jackson library.
JSONObject class has a method named "has". try this way,
if (json.has("name")) {
String status = json.getString("name"));
}
This will work
You can use Gson Java library to serialize and deserialize Java objects to JSON (as given below).
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(object, JsonObject.class);
Then, you can use the has method in JsonObject, to check if the key exists in it.
jsonObject.has(key)
Example:
Below is a method to check if given key exists in given json string, and get it's value.
(Instead of String, you can use your object as well. Here, I am considering the jsonStr as a String object, for better understanding.)
private String getValueFromJsonForGivenKey(String key, String jsonStr) {
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(jsonStr, JsonObject.class);
if (jsonObject.has(key)) {
// The given JSON string has the given key
String value = jsonObject.get(key).getAsString();
return value;
}
return null;
}
For key id and for jsonStr { "id": "1234" }, we get 1234.
For key name and for jsonStr { "id": "1234" }, we get null.
What you can do is to use JSONObject's opt method
eg.
JSONObject jsonObject = new JSONObject(myJSONString);
String name = jsonObject.optString("name");

Class cast Exception during JSON Parsing

I have been trying to parse this string to get the value of the Target-key
{
"Type" : "Notification",
"MessageId" : "something",
"Message" : "{\"buildId\":\"something\",\"somekey\":\"somevalue\",\"startTimeMillis\":1592526605121,\"table\":{\"key1\":\"val1\",\"tableName\":\"some table\",\"tableprop\":{\"bucketCount\":123,\"bucketColumns\":[\"X\",\"Y\"]},\"tableSortProperty\":{\"sortColumns\":[\"X\",\"Y\"]}},\"createStatementLocation\":{\"s3Bucket\":\"somebucket\",\"s3Prefix\":\"someprefix\"},\"Target-key\":\"Target-Value\"}",
"Timestamp" : "2020-06-19T19:23:46.378Z"
}
I have tried the following approach:
message.getBody() returns the Json String. Here message is the SQS Message object
Approach 1:
JSONObject jsonObject = new JSONObject(message.getBody());
JSONObject obj = (JSONObject) jsonObject.get("Message");
String res = (String)obj.get("Target-key");
I am getting the error at line 2 of above code
java.lang.String cannot be cast to org.json.JSONObject: java.lang.ClassCastException
java.lang.ClassCastException: java.lang.String cannot be cast to org.json.JSONObject
Approach 2:
Using Jackson also produces class cast exception on line2 again.
Map<String,Map<String,String> > mymap;
mymap = objectMapper.readValue(message.getBody(), Map.class);
Map<String, String> mymap2 = mymap.get("Message");
String res = mymap2.get("Target-key");
Approach 3:
Also Tried using Jackson Tree Node
However, the below solution do seem to work but I want to know why the above approach is failing
Map<String,String> messageMap;
messageMap = objectMapper.readValue(message.getBody(), Map.class);
Map<String,String> mmap = objectMapper.readValue(messageMap.get("Message"), Map.class);
String res = mmap.get("Target-key");
PS:I have tried many alternatives and similar question on stack overflow but it is not helping my case.
The actual key and value have been replaced with some-key and some-value.
EDIT:
I sneaked into the source data and updated JSON
Now that we can see the original source your problem is obvious. The value of Message is a string instead of a nested object.
JSONObject jsonObject = new JSONObject(message.getBody());
JSONObject obj= new JSONObject(jsonObject.getString("Message"));
There is a parsing error in your json at
"bucketCount": XYZ,
XYZ myst be inside inverted commas like "XYZ".
You can check your json at http://json2table.com
It fails because the result of parsing is not a String, nor Map<String,String> and not even a Map<String,Map<String,String>>. The result object has more complex structure.
If you need to have the object in yuor app for further use, you can create a class(es) to store and Jackson will deserialize it into object.
In case you don't need the whole object, there is readTree method on Jackson library.
It will create JsonNode object you can navigate with your tag names. Something like
res.get("Message").get("Target-key")
(consider properly formed input JSON)

Can't parse Java JSON string

From my server is get a JSON response like this:
String json = getJsonFromServer();
The server returns this reply (with the double quotes in the beginning and end):
"{\"error\":\"Not all required fields have been filled out\"}";
I then want to get the error field. I have tried to use the JSONObject class to get the string, but it does not work.
System.out.println("The error is: " + new JSONObject().getJSONObject(response).getString("error");
I have try
String response = "{\"error\":\"Not all required fields have been filled out\"}";
JSONParser parser = new JSONParser();
try {
JSONObject json = (JSONObject) parser.parse(response);
System.out.println(json.get("error").toString());
} catch (ParseException ex) {
}
It have working, you can try it and don't forget add json lib json-simple
You seem to be using the wrong JSONObject constructor; in your example, you are trying to fetch an object from a newlay created object - it will never exist.
Try this:
String response = "{\"error\":\"Not all required fields have been filled out\"}";
JSONObject json = new JSONObject( response );
String error = json.getString( "error" );
System.out.println( error );
Yields
Not all required fields have been filled out
edit
Now that you have completely changed the question...
Why not just first strip the first and last char?
So if
String response = "\"{\"error\":\"Not all required fields have been filled out\"}\"";
response = response.substring(1, response.length() - 1));
// Now convert to JSONObject
Your response object has exactly this string?
{"error":"Not all required fields have been filled out"}
The code below printed the expected output:
Object responseObject = "{\"error\":\"Not all required fields have been filled out\"}";
JSONObject jsonObject = new JSONObject(responseObject.toString());
String errorContent = jsonObject.getString("error");
System.out.println(errorContent);

org.json.JSONObject : automatically converts Empty String to Zero

I have a String :
jsonStr = {111:{Param1:1, Param2:, Param3:} ,112{Param1:, Param2:, Param3:}};
Which I am trying to convert into JsonObject (org.json.JSONObject).
JSONObject jObj = new JSONObject(jsonStr);
It is converting into valid JsonObject but 'Param2' which is having nothing as value, getting it value converted to 0.
I want that if a parameter is having empty value, I should get null when i access object :
jObj.getString('Param2').
Please share some pointers in this scenario.

java nested JSONArray

I want to know if it is possible to check if some key exists in some jsonArray using java. For example: lets say that I have this json string:
{'abc':'hello','xyz':[{'name':'Moses'}]}
let's assume that this array is stored in jsnArray from Type JSONArray.
I want to check if 'abc' key exists in the jsnArray, if it exists I should get true else I should get false (in the case of 'abc' I should get true).
Thnkas
What you posted is a JSONObject, inside which there is a JSONArray. The only array you have in this example is the array 'xyz', that contains only one element.
A JSONArray example is the following one:
{
'jArray':
[
{'hello':'world'},
{'name':'Moses'},
...
{'thisIs':'theLast'}
]
}
You can test if a JSONArray called jArray, included inside a given JSONObject (a situation similar to the example above) contains the key 'hello' with the following function:
boolean containsKey(JSONObject myJsonObject, String key) {
boolean containsHelloKey = false;
try {
JSONArray arr = myJsonObject.getJSONArray("jArray");
for(int i=0; i<arr.length(); ++i) {
if(arr.getJSONObject(i).get(key) != null) {
containsHelloKey = true;
break;
}
}
} catch (JSONException e) {}
return containsHelloKey;
}
And calling that in this way:
containsKey(myJsonObject, "hello");
Using regular expressions will not work because of the opening and closing brackets.
You could use a JSON library (like google-gson) to transform your JSON Array into a java array and then handle it.
JSON arrays don't have key value pairs, JSON objects do.
If you store it as a json object you can check the keys using this method:
http://www.json.org/javadoc/org/json/JSONObject.html#has(java.lang.String)
If you use JSON Smart Library in Java to parse JSon String -
You can parse JSon Array with following code snippet -
like -
JSONObject resultsJSONObject = (JSONObject) JSONValue.parse(<<Fetched JSon String>>);
JSONArray dataJSon = (JSONArray) resultsJSONObject.get("data");
JSONObject[] updates = dataJSon.toArray(new JSONObject[dataJSon.size()]);
for (JSONObject update : updates) {
String message_id = (String) update.get("message_id");
Integer author_id = (Integer) update.get("author_id");
Integer createdTime = (Integer) update.get("created_time");
//Do your own processing...
//Here you can check null value or not..
}
You can have more information in - https://code.google.com/p/json-smart/
Hope this help you...

Categories

Resources