I have the following code that uses Java JSON:
Widget w = new Widget(true, "LIVE");
WidgetService service = new WidgetServiceImpl(); // 3rd party JSON web service
JSONObject response = service.postWidget(w);
System.out.println("Response is: " + response.toString());
System.out.println("Now fetching orderid...");
System.out.println(response.getString("order_id"));
Don't worry about Widget or WidgetService: this question has to do with how I'm using the Java JSON API (and specifically JSONObject).
When I run the above code, I get:
Response is: {"response":{"credits_used":"0.30","job_count":1,"order_id":"243050","currency":"USD"},"opstat":"ok"}
Now fetching orderid...
Exception in thread "main" org.json.JSONException: JSONObject["order_id"] not found.
at org.json.JSONObject.get(JSONObject.java:473)
at org.json.JSONObject.getString(JSONObject.java:654)
at com.me.myapp.MyDriver.main(MyDriver.java:49)
As you can see, there is an order_id String field coming back in the response, and it has a value of "243050". So why am I getting the exception?
Your JSONObject response points to the outer json object.
I am pretty sure, your response object has a property "response" (and "opstat" btw.) containing your expected object.
You have to do it like this:
response.getJSONObject("response").getString("order_id");
Related
I am running a Java Servlet webserver which receives the following request:
http://localhost:8080/ForVen/Recebimento/recebeDispositivo.jsp?lista={"dispositivo":[{"Id":0,"DataMod":"2021-09-28T16:55:55.3528819-03:00","SeSincronizar":0,"NrVersaoReg":1,"DataSincronizacao":"2021-09-28T16:55:55.3538812-03:00","Guid":"BFEBFBFF000206A7","TipoDispositivo":0,"URL":"","VendedorId":1}]}
When I send it, it gives me the following error:
javax.servlet.ServletException: org.json.JSONException: Missing value at character 1 of {"dispositivo":[{"Id":0,"DataMod":"2021-09-28T16:55:55.3528819-03:00","SeSincronizar":0,"NrVersaoReg":1,"DataSincronizacao":"2021-09-28T16:55:55.3538812-03:00","Guid":"BFEBFBFF000206A7","TipoDispositivo":0,"URL":"","VendedorId":1}]}
If I try to send the same request, but with the JSON "formatted", it works.
http://localhost:8080/ForVen/Recebimento/recebeDispositivo.jsp?lista={"dispositivo":[{"Id":0,"DataMod":"2021-09-28T16:55:55.3528819-03:00","SeSincronizar":0,"NrVersaoReg":1,"DataSincronizacao":"2021-09-28T16:55:55.3538812-03:00","Guid":"BFEBFBFF000206A7","TipoDispositivo":0,"URL":"","VendedorId":1}]}
This is the way I am deserializing the JSON:
JSONObject jso = new JSONObject(myIncomingJson);
I don't know if it has something to do with some Apache configuration, but I hope so, it would be extremely painful to change all of the client-side requests.
As f1sh said, I have to encode the JSON that is being send on the URL, my mistake that I didn't saw it. :)
This is how the URL should be:
http://192.168.1.58:8080/ForVen/Recebimento/recebeDispositivo.jsp?lista=%7B%5C%22dispositivo%5C%22%3A%5B%7B%5C%22Id%5C%22%3A0%2C%5C%22DataMod%5C%22%3A%5C%222021-09-30T09%3A15%3A37.4138271-03%3A00%5C%22%2C%5C%22SeSincronizar%5C%22%3A0%2C%5C%22NrVersaoReg%5C%22%3A1%2C%5C%22DataSincronizacao%5C%22%3A%5C%222021-09-30T09%3A15%3A37.4148274-03%3A00%5C%22%2C%5C%22Guid%5C%22%3A%5C%22BFEBFBFF000206A7%5C%22%2C%5C%22TipoDispositivo%5C%22%3A0%2C%5C%22URL%5C%22%3A%5C%22%5C%22%2C%5C%22VendedorId%5C%22%3A1%7D%5D%7D
I created a program to get an API response from a URL.
But for some reason it's printing it out in one long line. Is there any way to print it out the way I see it in postman? I guess what I mean is if there is a way to see the response from the API server printed out line by line instead of one long line.
ResponseBody body = response.getBody();
System.out.println("Response Body is: " + body.asString());
The server response is
[RemoteTestNG] detected TestNG version 6.13.1
Status code is 200
Response Body is:
{"request_id":"Z36ec5ee76a4788bfe83655edbbe9f0","status":"OK","data":{ONE LONG STRING OF DATA WITH NO END IN SIGHT!}
You can use prettyPrint method of Response class. Status you will have to print.
(Response to comment)
If your API call return JSON responses, you can use a JSON validator module.
What it does is: you provide a JSON schema, and it compares it with the response. The JSON schema syntax is defined over there: http://json-schema.org/latest/json-schema-validation.html (it looks more complex than it actually is) and here are some examples http://json-schema.org/examples.html. You can define, in your schema, if a field is "required", and also which "type" it should be (string, integer etc.) and many other things!
Here's a simple tutorial that helped me implement it with Rest-Assured: https://blog.jayway.com/2013/12/10/json-schema-validation-with-rest-assured/
I'm testing REST API and while I make GET call to retrieve resources, it's resulting into 500 Internal Server Error and in output it's returning message which has media type application/json:
[
{
"messageType": "Some error type",
"messageText": "Some message text",
"moreInfo": "Some info"
}
]
Please make note that in above output, Json is inside []
I want to read value of messageText from above output response. I tried with -
JsonObject jsonObject = response.readEntity(JsonObject.class);
but it results in following error:
java.lang.IllegalStateException: Entity input stream has already been closed.
at org.glassfish.jersey.message.internal.EntityInputStream.ensureNotClosed(EntityInputStream.java:225)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:830)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:783)
at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:326)
at org.glassfish.jersey.client.InboundJaxrsResponse$1.call(InboundJaxrsResponse.java:111)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:399)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:108)
Could you please help me how can I read the message in output? I'm using Jersy library.
According to javaDoc, a call to readEntity closes the response entity, so when you make another readEntity call you get IllegalStateException.
Unless the supplied entity type is an input stream, this method
automatically closes the an unconsumed original response entity data
stream if open.
In my case, having the expression response.readEntity(String.class)
in the Expressions pane in the Debug perspective caused this exception when I ran the code in Debug mode. The evaluation of the expression consumed the entity and caused it to close.
I solved this by first doing the readEntity to a String entity and then using the Jackson ObjectMapper to actually deserialize to the target class.
Problematic code:
Transactions transObj = response.readEntity(Transactions.class);
Solution:
String stringEntity = response.readEntity(String.class);
Transactions transObj = objectMapper.readValue(stringEntity, Transactions.class);
It seems this problem arises when the JSON string in the response entity stream is very long or complex possibly requiring multiple interactions thereon. 'Deserializing' to a string seems to only require a single bite. Once you have the string (and Jackson or GSON) de-serialization to target entity takes place without touching the response.
Actually it is a issue with how are we defining the reference of Response object .
Solution is weird
Not Working one :
Response response;
if (condition) {
response =
} else {
response =
}
String resp = response.readEntity(String.class);
if (response.getStatus() == 200) {}
Working One
Response response = null;
if (condition) {
response =
} else {
response =
}
String resp = response.readEntity(String.class);
if (response.getStatus() == 200) {}
So basically if we wont assign anything to response initially , Stream will be closed
When you get your error 500 you probably get another exception in the console/log. You should start checking that and then trying to resolve this one. If you don't find anything in the log, could you please post more code?
When i invoke next code:
Response response = target.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
response.getEntity();
response.getEntity() is always null.
But when i invoke:
JsonObject json = target.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE), JsonObject.class);
variable json is not null.
I need to use first variant because i need to check response status.
Why the first code is not working?And how can i get status code then?
You need to use response.readEntity(Your.class) to return the instance of the type you want. For example
String rawJson = response.readEntity(String.class);
// or
JsonObject jsonObject = response.readEntity(JsonObject.class);
Note that there actually needs to be a provider to handle reading that Java type and application/json. If you are using the Jersey and the JSON-P API, see this. Also for general information about providers, see this
I am getting different type of JSON response out of HTTP request API. There are might be couple of JSON format option coming back from API. For example it might be valid response with expected data but in some cases it might be internal server error detailed message.
At the moment I am using Gson to convert incoming string into the object, but since sometimes it comes as different format Gson not able to convert it as different template class is provided.
NOTE:
Error does not mean an exception. For example JSON body contain just information that authentication is failed for example, but call was made successfully and JSON body is VALID. HTTP is actually always successful and will be 200. Problem is that sometimes authentication might fail and it will return different JSON.
String response = restTemplate.getForObject(request, String.class);
ObjectResponse objResponse = gson.fromJson(response, ObjectResponse.class);
Could you please suggest better way of doing it so that I can handle different types of responses? Or maybe you know completely different way of doing it.
Thanks!
If you can't predict the structure of the response, map it to a tree of simple Java maps, arrays, and strings. The Jackson library supports this with 'readTree' methods. Once you look at the tree and decide what it is, you can then ask the library to map a tree to an object of a class.
One option is to make a class representing the JSON data, and deserialize into that. This way, if the data does not match that structure, you will get an exception.
When you try and create your object and it fails, catch the exception and try and decode it as an error - you can then deal with that case as you wish (and the potential case where it is neither the object you expect or a valid error).
Check HTTP Response Codes. If you receive a status code that isn't OK(200) then you shouldn't try to parse for a successful response. For instance you may check the code and handle response like this (the object types are not actual Java types, but are given to provide an example):
MyHttpResponse response = MyHttpHelper.execute(...);
int status = response.getMyStatusCode();
String responseData = response.getStringBody();
switch(status) {
case 200: {
//request is successful, parse valid data
break;
}
default: {
//request is not valid, parse error data
break;
}
}