how to accept json array input in jersey Rest Webservice - java

Am developing a rest webservice using Jersey.Am slightly new to webservices. I need to pass List of customer as input to rest webservice. having issue in achieving it.
Below is my customer object class
#Component
public class customer {
private String customerId;
private String customerName;
And my endpoint is as below. addCust is the method that will be called on calling the webservice
#Path("/add")
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
public String addCust(#Valid customer[] customers){
//And json input is as below
{customers:{"customerId":"1","customerName":"a"},
{"customerId":"2","customerName":"b"}}
But jersey is not able to convert json array to Array of Customers. It is returning 400. And the logs shows "no viable alternative at c". How to pass Json array as input to webservice and convert into Array or ArrayList. Any help appreciated.

Your json is invalid, field names should be always double quotted, and arrays are placed inside [] for example:
{"customers":[{"customerId":"1","customerName":"a"},
{"customerId":"2","customerName":"b"}]}
thats why jackson cannot unmarshall it. But this json will never fit your api.
Here is an example of what You should send:
[{"customerId":"1","customerName":"a"},{"customerId":"2","customerName":"b"}]
Another thing is that You can use collections instead of arrays:
#Path("/add")
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
public String addCust(#Valid List<Customer> customers){
If you want to send a json like this:
{"customers":[{"customerId":"1","customerName":"a"},
{"customerId":"2","customerName":"b"}]}
then you have to wrap everything into class with "customers" property:
class AddCustomersRequest {
private List<Customer> customers;
public void setCustomers(List<Customer> customers) {
this.customers = customers;
}
public void getCustomers() {
return this.customers;
}
}
And use it in Your API:
#Path("/add")
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
public String addCust(#Valid AddCustomersRequest customersReq){

Related

How to print null values in the JSON rest webservice response in Java?

I have the below method in my rest service test class.
#Override
#JsonInclude(JsonInclude.Include.ALWAYS)
#GET
#Produces("application/json")
#Path("/list")
public List<XXX> findAll() {
System.out.println("inside wrapper class findall");
return super.findAll();
}
The JSON response does not print any null value fields in the response.
e.g.- It prints {"key":"1","value:2"} instead of {"key":1, "value":2, "dvalue":null}
I tried using #JsonInclude(JsonInclude.Include.ALWAYS) but that is not working either. I am using jackson-annotations-2.0.4 jar.
Please let me know what might I be missing.

How to parse RESTful API params with Dropwizard

Let's say I have:
#GET
public UserList fetch(#PathParam("user") String userId) {
// Do stuff here
}
Now, let's say I have my own type for userId, let's call it UserId. Is it possible to parse that String to UserId when it is passed into the fetch method, i.e.:
#GET
public UserList fetch(#PathParam("user") UserId userId) {
// Do stuff here
}
I realize I can parse the String once I am inside the method, but it would be more convenient that my method gets the type I want.
Well you've attempted to make a GET call with a request body is what I find not very helpful. Do read Paul's answer here -
you can send a body with GET, and no, it is never useful to do so
What would be good to practice is, to make a PUT or a POST call (PUT vs POST in REST) as follows -
#POST
#Path("/some-path/{some-query-param}")
public Response getDocuments(#ApiParam("user") UserId userId,
#PathParam("some-query-param") String queryParam) {
UserId userIdInstance = userId; // you can use the request body further
Note - The ApiParam annotation used is imported from the com.wordnik.swagger.annotations package. You can similarily use FormParam,QueryParam according to your source of input.
Dropwizard is using Jersey for HTTP<->Java POJO marshalling. You could use the various annotations from Jersey #*Param (#FormParam, #QueryParam, etc.) for some of the parameters.
If you need to use map/marshall to/from Java POJOs take a look at the test cases in Dropwizard:
#Path("/valid/")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class ValidatingResource {
#POST
#Path("foo")
#Valid
public ValidRepresentation blah(#NotNull #Valid ValidRepresentation representation, #QueryParam("somethingelse") String xer) {
return new ValidRepresentation();
}
This defines an API endpoint responding to HTTP POST method which expects ValidRepresentation object and "somethingelse" as HTTP method query parameter. The endpoint WILL respond ONLY when supplied with JSON parameters and will return only JSON objects (#Produces and #Consumes on the class level). The #NotNull requires that object to be mandatory for the call to succeed and #Valid instructs Dropwizard to call Hibernate validator to validate the object before calling the endpoint.
The ValidRepresentation class is here:
package io.dropwizard.jersey.validation;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
public class ValidRepresentation {
#NotEmpty
private String name;
#JsonProperty
public String getName() {
return name;
}
#JsonProperty
public void setName(String name) {
this.name = name;
}
}
The POJO is using Jackson annotations to define how JSON representation of this object should look like. #NotEmtpy is annotation from Hibernate validator.
Dropwizard, Jersey and Jackson take care of the details. So for the basic stuff this is all that you need.

POJO attributes is returning as a Array for JSON in JAX-RS

I have a java web maven project with JAX-RS using resteasy version 2.2.1.GA implementation. All JAX-RS resources on the project produces y consumes application/json. My problem is that when I returning a single POJO, even an array of this, only serialize the values of the attributes.
Example:
Given the following classes:
public class Pojo {
private Integer attr1;
private String attr2;
// GETTERs and SETTERs
}
#Path("pojos")
#Consumes("application/json")
#Produces("application/json")
public class PojoResource {
#GET
public Response list() {
List<Pojo> listResult = new ArrayList<>();
Pojo pojo = new Pojo();
pojo.setAttr1(1);
pojo.setAttr2("asdf");
listResult.add(pojo);
return Response.ok().entity(listResult).build();
}
}
If I do a GET request to /pojos, the result for the example above is [[1, "asdf"]], instead of [{"attr1":1,"attr2":"asdf"}]
I don't know if a need to write a specific Provider. My project configuration is similar to this.
I realized my mistake is that data recovery in layer model is as a vector of objects and return that without processing (create a POJO that represent the data).

How correctly produce JSON by RESTful web service?

I am writing a web service the first time. I created a RESTful web service based on Jersey. And I want to produce JSON. What do I need to do to generate the correct JSON type of my web service?
Here's one of my methods:
#GET
#Path("/friends")
#Produces("application/json")
public String getFriends() {
return "{'friends': ['Michael', 'Tom', 'Daniel', 'John', 'Nick']}";
}
Is it sufficient that I simply point out annotation #Produces("application/json") for my method? Then this method may return any type of object? Or only String? Do I need additional processing or transformation of these objects?
Please help me as a beginner to deal with these issues. Thanks in advance!
You can annotate your bean with jaxb annotations.
#XmlRootElement
public class MyJaxbBean {
public String name;
public int age;
public MyJaxbBean() {} // JAXB needs this
public MyJaxbBean(String name, int age) {
this.name = name;
this.age = age;
}
}
and then your method would look like this:
#GET #Produces("application/json")
public MyJaxbBean getMyBean() {
return new MyJaxbBean("Agamemnon", 32);
}
There is a chapter in the latest documentation that deals with this:
https://jersey.java.net/documentation/latest/user-guide.html#json
You could use a package like org.json http://www.json.org/java/
Because you will need to use JSONObjects more often.
There you can easily create JSONObjects and put some values in it:
JSONObject json = new JSONObject();
JSONArray array=new JSONArray();
array.put("1");
array.put("2");
json.put("friends", array);
System.out.println(json.toString(2));
{"friends": [
"1",
"2"
]}
edit This has the advantage that you can build your responses in different layers and return them as an object
#GET
#Path("/friends")
#Produces(MediaType.APPLICATION_JSON)
public String getFriends() {
// here you can return any bean also it will automatically convert into json
return "{'friends': ['Michael', 'Tom', 'Daniel', 'John', 'Nick']}";
}
#POST
#Path ("Employee")
#Consumes("application/json")
#Produces("application/json")
public JSONObject postEmployee(JSONObject jsonObject)throws Exception{
return jsonObject;
}
Use this annotation
#RequestMapping(value = "/url", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON})

JSON Parsing with JAX-RS

I am building an REST API with JAX-RS. I have POST that consumes an JSON element:
The element is a class:
#XmlRootElement
public class EventData{
public long start;
public long end;
public Collection<Person> persons;
}
I have an method like this:
#POST
#Consumes({MediaType.APPLICATION_JSON})
public Response transactionRequest(EventData insert){
....}
if I post a JSON String of an EventData it works fine, but if I switch to:
#POST
#Consumes({MediaType.APPLICATION_JSON})
public Response transactionRequest(ArrayList<EventData> insert){
....}
and send an JSON String like this "{eventData:[{start:x,end:y,persons:[....]}]" it will build the ArrayList and its EventData objects, but the EventData object variables are null.
Can anybody help?
You need to send a JSON array consisting of JSON objects representing your EventData class.
The sample you've given isn't such a JSON array, but a JSON object with a single property named 'eventData' containing an JSON array.
Try something like this (based on your EventData class):
[
{ "start":1, "end":2, "persons":[] },
{ "start":3, "end":4, "persons":[] }
]
Notice that there is no mention of your EventData class, because JSON has no concept of named types -- it's just objects and arrays of objects; only the properties of objects have names.

Categories

Resources