I was developing a restful web client and trying to get the JSON payload from the response of a GET method. I am using Jersey. But I just cannot read the JSON data using response.getEntity() method. I tried many methods including response.bufferEntity(), but the output always kept empty. Below is my code and output, and in addition I can see the JSON data right in the response packet captured in wireshark. I would really appreciate everyone trying to help figure out why or provide solution. Thank you!
Code:
public JSONObject Get(String requestPath){
ClientResponse response = webResource.path(requestPath)
.header("Content-Type", contTypeHeader )
.header("Accept",acceptHeader)
.header("Authorization", authZ )
.get(ClientResponse.class);
response.bufferEntity();
if (!(response.getStatus() == 201 || response.getStatus() == 200)) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
System.out.println(response.getEntity(JSONObject.class));
return null;
}
and the output is always like this: {}
You can't use JSONObject unless you have a MessageBodyReader for it. See more at JAX-RS Entity Providers. The provider you are currently using (probably Jackson) only supports JavaBean POJOs or collections of them. For example if you have this JSON
{ "property1" : "value1", "property2": "value2" }
Then you would need to have a POJO like
public class Bean {
private String property1;
private String property2;
// getters and setters
}
Then you can do getEntity(Bean.class). The reason you are getting an empty object, is that the deserialization works off the setters. It looks for properties on the JSON, that matches a setters, and uses it the set the property. The JSON object has no setters for your JSON properties.
Related
Being new to Java/JSON/REST Assured topics, I would like to extract a parameter of "token": from a JSON response body as a String and store it as variable which I could take to some other classes and use there. However, I have tried it and have not found a way. Below is part of a code which I have created at the beginning in a same manner as other requests stored in this class, but this is the first one from which I need something from the response:
public FakeTokenVO fakeToken() {
String payload = "payloadthere";
return given(specBuilder.fakeTokenRequestSpecification()) .
body(payload)
.log().all()
.when()
.post(RestApiRoutes.FAKE_URI)
.then()
.log().all()
.extract()
.response()
.as(FakeTokenVO.class);
}
Don't mind about the payload and those VO classes as it is stored as data model somewhere else.
Response from the request made looks like this:
{
"createTokenResponse": {
"createTokenSuccess": {
"token": "token_with_somewhere_about_700_characters"
}
}
}
Here is how I have tried to modify it to get the part of response which I need later (the token to authorize other requests):
#Test
public void fakeToken()
{
String payload = "payloadthere";
String token = given(specBuilder.fakeTokenRequestSpecification())
.body(payload)
.log().all()
.when()
.post(RestApiRoutes.FAKE_URI)
.then()
.log().all()
.extract()
.response()
.body().path("createTokenResponse.createTokenSuccess.token");
System.out.print(token);
}
This test returns me a value which I needed, but I do not know how to implement it as a method instead of test. Please help how should I approach it? What am I missing there? I tried to search for answers, but I haven't found a solution yet or do not know how to implement it in my part of the code.
I assume that you can get your response as a String. So all you need to do is to parse your Json String. For that you can use any available Json parser. The most popular ones are Json-Jackson (also known as Faster XML) or Gson (by Google). Both are very well known and popular. (My personal preference is Jackson, but it is a matter of opinion).
However, For simplistic cases like this I wrote my own utility (a thin wrapper over Jackson library) that allows you to parse Json String very simply without learning relatively complex libraries. With my utility your code may look like this:
try {
Map<String, Object> map = JsonUtils.readObjectFromJsonString(jsonStr, Map.class);
Map<String, Object> innerMap = map.get("createTokenResponse");
Map<String, Object> innerMap2 = map.get("createTokenSuccess");
String token = innerMap.get("token");
} catch (IOException e) {
e.printStacktrace();
}
Or you can create your own classes such as
public class TokenResult {
String token;
//getter and setter
}
public class TokenHolder {
private TokenResult createTokenSuccess;
//setter and getter
}
public class TokenResponse {
private TokenHolder createTokenResponse;
//setter and getter
}
And than your code may look like this:
try {
TokenResponse response = JsonUtils.readObjectFromJsonString(jsonStr, TokenResponse .class);
String token = response.getCreateTokenResponse().getCreateTokenSuccess().getToken();
} catch (IOException e) {
e.printStacktrace();
}
Here is a Javadoc for JsonUtils class. This Utility comes as part of Open Source MgntUtils library written and maintained by me. You can get the library as maven artifact on Maven Central here or on the github (including source code and javadoc)
If the POST / PATCH body needs to look like this
{
"class_name" : {
"field_a" : "fjdksljf"
"field_b" : "jfsljd"
...
etc.
}
}
and I have a POJO
public class ClassName () {
#SerializedName("field_a")
String fieldA;
#SerializedName("field_b")
String fieldB;
... etc.
}
and I want to pass it as
#PATCH("endpoint_url")
Call<ResponseBody> testFunction(#Body ClassName class)
How can I annotate the class itself with the class_name mapping needed for the JSON request without creating a RequestClass that wraps ClassName and annotates it with serialized name there?
(I tried annotating the class with #SerializedName but it gives me a "not applicable to type" warning.)
This ended up being a good solution for me. While it is possible to wrap it in another class, it doesn't really make sense in my use case since most of my POST bodies require a JSON key for the POJO I'm sending.
// to use the necessary #SerializedName annotations
String classNameJson = new Gson().toJson(className); // {"field_a": "fjdksljf", "field_b" : "jfsljd", ... etc.}
JSONObject json = new JSONObject();
try {
// must make this a new JSONObject or else it will handle classNameJson as a string and append unnecessary quotes
json.put("class_name", new JSONObject(classNameJson));
} catch (JSONException e) {
// handle the error
}
String result = json.toString();
Result should print something like this {"class_name":{"field_a": "fjdksljf", "field_b" : "jfsljd", ... etc.}}
Got this idea from the following posts:
single key value to Json with Gson
JSONObject.toString: how NOT to escape slashes
Java Append object to JSON
I am new to java and creating some Restful services in netbeans using jersey framework.
I have created many GET, POST web services which is having different different type of responses which are basically Model Objects and depending upon media type I am getting JSON or XML.
Some response is having only a single object which is being shown in JSON inside {}, and some are list which are in [].
I want to see a generic response format for all api responses.
Example-
{"status":"0 or 1", "message":"any string message","result":"it can be a single object or a list of objects which is dynamic depending upon each web service response"}.
Since here in java we need to created model objects for getting responses so I have created a ResponseModel which is having a status property , message property but don't know the type of result property because sometime it can have a single object or sometime a list so what type should I set for this property so that I can assign any thing to this and response will always be in same format for JSON or XML.
I have created a static method with constructor which takes all these three parameters and create a ResponseModel object.
Thanks in advance
EDITED- Code after Using "Object" as generic type
public static Response getResponseObjectIsValid(boolean isValid, String message,Object result)
{
if (isValid == true) {
LGSResponse response = new LGSResponse();
response.setStatus(1);
response.setMessage(message.length()>0 ? message : "Success");
response.setResult(result);
return Response.status(Status.OK).entity(response).build();
}
else
{
LGSResponse response = new LGSResponse();
response.setStatus(1);
response.setMessage(message.length()>0 ? message : "Failed");
response.setResult(result);
return Response.status(Status.OK).entity(response).build();
}
}
Result Parameter is a normal model object.
You can simply create your class as you've said.
public class ResponseModel {
int status;
String message;
Object result;
// contructor, getters, setters go here...
// (probably consider using lombok, but that is a story for another time)
}
Then you can pass either a single object or an array as the 3rd param and the json/xml serializer should take care of the conversion for you unless your objects are very complex(I rarely run into that problem)
For example, your Jersey methods would look something like this:
// returning a single object within the response model
#GET
#Path("/myMethod")
public Response aJerseyMethod() {
Book aBookObject = new Book("The Title", "Name of Author");
ResponseModel responseModel = new ResponseModel(1, "This is a book", aBookObject);
return Response.ok(responseModel)
.build();
}
// returning an array within the response model
#GET
#Path("/myOtherMethod")
public Response anotherJerseyMethod() {
Book aBookObject = new Book("The Title", "Name of Author");
Book anotherBookObject = new Book("The Other Title", "Name of another Author");
ArrayList<Book> aBookArray = new Arraylist();
aBookArray.add(aBookObject);
aBookArray.add(anotherBookObject);
ResponseModel responseModel = new ResponseModel(1, "These are books", aBookArray);
return Response.ok(responseModel)
.build();
}
In both cases you should get the expected output you were talking about and you do not have to do any additional checks or conversions yourself.
I just wrote this here, so try it out with your own classes instead of "Book" (which is not a real class) and let me know if it works.
You should not maintains status code, message and result within json body.
Response message should only contain the result of that api.
Httpstatus code will be the status code (Ex.200 is success, 404 is notfound)
All the other info should be maintained in response headers, not within json body
I get a list of object from server. One key of this objects is called body, and it is a json. It is almost impossible for me to know its keys : the key name and size of it (body) are different.
Example of data
data from server = [object, object, object,.....]
object = {
id: 1,
name: "xyz",
body": {
x: "xyz",
y: "xyz",
z: "xys",
}
}
I edit the body and then post it to the server together with the id of the object. Until here it is fine. I can send the request but can not handle the Requestparam which is of type json.
How to handle this post request on the backend built in Java and Spring?
You have to add a #RequestBody annotation to the method on the Controller such as:
#RequestMapping ("url/to/save")
#ResponseBody
public ResponseObject send (#RequestBody RequestObject myRequestObject)
{
//do something
return new ResponseObject ();
}
The RequestObject would be the Java Class mapping to the JSON you want to save. The ResponseObject is whatever you want to return, you could also return void but Firefox has issues with that sometimes.
I'm trying to use Jersey to develop a REST web service. My requirement is for me to be able to access the web service and return data, based on the passed PatParam parameters. My web service so far is as follows:
#GET
#Produces(MediaType.APPLICATION_JSON)
#Consumes({ "application/xml", "application/json", "application/x-www-form-urlencoded" })
#Path("/1.0/people{extension:(.json)*}/{personId:([^/]+?)?}{entityExtension:(.json)*}")
public String getLocation(#PathParam("extension") String extension, #PathParam("personId") String personId,#PathParam("entityExtension") String entityExtension)
{
if ((personId==null ||personId.equals("")) && (extension == null || extension.equals("")))
return "No Id, and no extension";
else
return "personId= "+personId + ", extension= " + extension+", entityExtension= "+entityExtension;
}
With the above code in mind, what I'm trying to achieve is the following:
http://localhost:8080/Jersey/RestService/1.0/people.json
Should return the list of all people in the "json" format (Hence the .json extension)
Now, I want to be able to get the information for a particular person by simply putting the person's ID, and return the person's information in json/xml based on the extension:
http://localhost:8080/Jersey/RestService/1.0/people/Mouhammed89.json
With the above URL, I should be returning the information for the personId: Mouhammed89, and returning the information in the json format.
I know that my problem is with the regular expressions that I'm using, so I would really appreciate the help in creating them.
IMHO container (List) and item (Person) URL should be handled separately.
And you don't require explicit .json prefix for returning JSON response, only the annotation at the API level should suffice.
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/1.0/people") //no need for .json suffix as API only return JSON format
public List<String> allLocations(..){ //jackson etc. will convert return type to json string
..
}
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/1.0/people/{personId: \\d+}")//digits only
public String getLocation(..){ //jackson etc. will convert return type to json string
..
}