Write RequestBody for Restful method - java

I'm a new member in Restful API, I'm writing a GET method:
#RequestMapping(method = RequestMethod.GET, value = "/resourcerecords", produces={"application/json", "application/xml"})
public #ResponseBody Object getRRs(#RequestBody RRRequest requestBody){
// do something
}
The RRRequest class:
public class RRRequest{
private RRREC reqObject;
// getter and setter
}
The RRREC class:
public class RRREC{
protected String infraAddr;
protected RRINFRATYPE infraType;
// getter and setter
}
And the RRINFRATYPE class:
public enum RRINFRATYPE {
V_6_ADDRESS("V6ADDRESS"),
OBJECT("OBJECT"),
ZONE("ZONE"),
V_4_REVERSEZONE("V4REVERSEZONE"),
V_6_REVERSEZONE("V6REVERSEZONE"),
NODE("NODE"),
ALL("ALL");
private final String value;
RRINFRATYPE(String v) {
value = v;
}
public String value() {
return value;
}
public static RRINFRATYPE fromValue(String v) {
for (RRINFRATYPE c: RRINFRATYPE.values()) {
if (c.value.equals(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}
}
Then, I sent a request GET with RequestBody ( I use Fiddler Web Debugger)
"reqObject" : {
"infraAddr" : "192.168.88.4",
"infraType": {
"value": "OBJECT"
}
}
I get 400 Bad Request. If I change to
"reqObject" : {
"infraAddr" : "192.168.88.4",
"InfraType": {
"value": "OBJECT"
}
}
I can debug.
However, The reqObject only receive infraAddr with "192.168.88.4", the InfraType is null.
Who can explain to me, why I must be use "InfraType" instead of "infraType" and how to send value for InfraType.

The first one is when your api in GET method you still cant send body of request to server, try to change it to POST.
Because you use ENUM in your Object so you should define a converter like Converting JSON to Enum type with #RequestBody
But in this case, I think the fastest way is change infraType to String and use switch case with String on server side.
public class RRREC{
protected String infraAddr;
protected String infraType;
// getter and setter
}
Your JSON will be:
{
"reqObject" : {
"infraAddr" : "192.168.88.4",
"infraType": "OBJECT"
}
}

Related

Java. Cast generic List to list of objects from factory

Is it possible to cast List Objects to List of Objects from Factory pattern?
I have a Jersey REST endpoint and I migrate data from one environment to another. I wish to post some list of Object and cast them to right object taken from factory pattern
#Path("/migrateTableAtOnce")
#Consumes(MediaType.APPLICATION_JSON)
public <T> Response saveObjectIntoDb(List<T> listOfObj) {
// if listOfObj.getTableName() == "MW_ID_GENERATOR" tableOject gets new MwIdGenerator()
myEntity tableObject = myEntityFactory.getTable(listOfObj.getTableName());
return Response.status(201).entity("ok").build();
}
Is it possible that I have only one post method which that generic List. I have 20 objects which I need to transfer and I dont want to write 20 post methods :( I dont know how to do it exactly.
One of my method looks like that:
#POST
#Path("/migrateTableAtOnceMwIdGenerator")
#Consumes(MediaType.APPLICATION_JSON)
public Response saveObjectIntoDb(List<MwIdGenerator> listOfObj) {
Boolean result = false;
String dbResponse ="";
try {
dbResponse = obtainFacade().saveToDb(listOfObj);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return Response.status(201).entity(result+" "+dbResponse).build();
}
Is there no better solution to solve this problem?
I post the body as a custom object, and have a list within that object like;
#POST
#Path("/migrateTableAtOnceMwIdGenerator")
#Consumes(MediaType.APPLICATION_JSON)
public Response saveObjectIntoDb(CustomObject object) {
List <Stuff>list = object.getList();
and the object
public class CustomObject extends Serializable {
public List <Stuff>sList = null;
public List <OtherStuff>osList = null;
public List <TheBestStuff>tbsList = null; //etcetc
public List getList ()
{
return list;
}
public void setList(List <Stuff>list)
{
this.list = list;
}
public List getOsList ()
{
return osList ;
}
public void setList(List <OtherStuff>osList)
{
this.osList = osList;
}
public List getTbsList ()
{
return tbsList;
}
public void setTbsList(List <TheBestStuff>tbsList)
{
this.tbsList = tbsList;
}
and Jersey can parse the json object into your custom object, provided that you can pass the fields of that class as json. Seeing as you're passing the data with json, you're limited as to your implimentation as json only covers String, int, boolean and simple date, but you can pass most values as String and then parse.

How to use Type interface to pass while class initialization of generic<T>?

We are parsing okhttp response objects using GSON.
In order to allow a generic parsing logic, We had opened to pass a type of response using setType(Type type) and now using below code to parse all responses.
Object mResponse = mGson.fromJson(response.body().string(), mType);
As this code is not open for a change I have extended this class and overridden the parse response method. I have also created a new class called MyRespose and want to initialize with whatever type is passed in setType method so that the consumers are returned the object of what type they have passed instead of an instance of Object class.
public class MyResponse<T> {
private int mStatus;
private T mResponseData;
public MyResponse(int status, T responseBody) {
this.mStatus = status;
mResponseData = responseBody;
}
public MyResponse(T responseBody) {
mResponseData = responseBody;
}
public int getStatus() {
return mStatus;
}
public void setStatus(int status) {
this.mStatus = status;
}
public T getResponseData() {
return mResponseData;
}
public void setResponseData(T responseData) {
mResponseData = responseData;
}
}
How can I use the Type(interface) to pass as so that the when someone calls getResponseData it return the object of type which is passed in setType instead of a generic Object ?
Something like
Object mResponse = mGson.fromJson(response.body().string(), mType);
mMyResponse = new MyResponse<???>(response.code(), mResponse );
How can i use mType to pass at place of "???"
I think, you can make use of TypeToken here. Its included in Gson and should go like this.
Type responseType = new TypeToken<MyResponse<XYZ>>() {}.getType();
gson.fromJson(json, responseType);
You can read further on this here

Array of object as request body in restassured

I usually able to create class as input for .body() and rest-assured read all the data correctly, but not with array.
I tried declaring the object class as an array, but rest-assured didn't accept it correctly as I want.
Can I send array of object as .body when using rest-assured?
Request Body
[
{
"product_type" : "1",
"request_by" : "android",
},
{
"product_type" : "2",
"request_by" : "ios",
}
]
The class I make
public class ProdReq {
private String product_type;
private String request_by;
public String getProduct_type() {
return product_type;
}
public void setProduct_type(String product_type) {
this.product_type = product_type;
}
public String getRequest_by() {
return request_by;
}
public void setRequest_by(String request_by) {
this.request_by = request_by;
}
The code I use to get response
ProdReq[] prodReq = new ProdReq[2]
//set the data
......
given().when().body(prodReq).post({{api_url}}).then().extract().response();
Should I make a JSONObject of the class (if possible), then put them in a JSONArray?
#GFB Did you set up the ContentType? Try to use something like this:
List<ProdReq> prodReq = new ArrayList<>();
... set up the data.
given().contentType(ContentType.JSON).when().body(prodReq).post({{api_url}}).then().extract().response();
I'm using serialization of the object to JSON body without any problems in my project.

How can I find the JSON key of a field (jackson)?

I have the following problem: I export my user object as usual with the jackson.databind.ObjectMapper and that works fine: ({"address":{"village":"NY"},"prename":"Joe"}).
Now I have to get the key (for address and prename) with Java reflection.
If the field has the annotation #JsonProperty, there is no problem to get this key. But this annotation isn't pressent on all fields (for example the m_address field).
At How does the Jackson mapper know what field in each Json object to assign to a class object? I read that the ObjectMapper tries to call the getter or so.
But I have no clue how I can find the right getter to my field.
I know that this isn't probably the most beautiful way to solve my problem, but I haven't found any method on the ObjectMapper like: mapper.getJSONKeyByName(field).
If something like that exist even better. :)
Is there a way to find the right getter to a field and does something like mapper.getJSONKeyByName(field) exist on the ObjectMapper?
Main.java
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// Object to JSON as usual
mapper.writeValue(System.out, new User("Joe", new Address("NY")));
// {"address":{"village":"NY"},"prename":"Joe"}
// Lookup with reflection
for (Field field : User.class.getDeclaredFields()) {
field.setAccessible(true);
try {
if (field.isAnnotationPresent(JsonProperty.class)) {
System.out.println("JSON-Key with annotation: " +
field.getAnnotation(JsonProperty.class).value());
// JSON-Key with annotation: prename
} else {
//TODO do something to get "JSON-Key without annotation: address
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
User.java
public class User implements Serializable {
#JsonProperty(value="prename")
#Validationinfo(name="prename", required=true, maxlenght=20)
private String m_name;
private Address m_address;
public User(String name, Address a) {
m_name = name;
m_address = a;
}
#JsonIgnore
public String getName() {
return m_name;
}
public void setName(String name) {
m_name = name;
}
public Address getAddress() {
return m_address;
}
public void setAddress(Address address) {
m_address = address;
}
}
Address.java
public class Address implements Serializable {
#JsonProperty(value="village")
#Validationinfo(name="village", required=false, maxlenght=10)
private String m_village;
public Address(String village) {
m_village = village;
}
public String getVillage() {
return m_village;
}
public void setVillage(String village) {
m_village = village;
}
}
EDIT:
The code is simplified. I have a REST service which does the writeValue part. The reflection part is done in a static recursive method on the User.
The thing is I have a custom Validationinfo annotation (with things like required, maxlength and so on) on my fields and also a name parameter. This name is the same as it is on the #JsonProperty annotation.
On an JavaScript application I want merge the value of the user fields with the ValidationInfos. For that I have to ensure that every validationInfos->name is unique. So I have to prefix the annotated Vaditioninfo->name whith the JSON serialized name/key of its parent (see in the REST respons "address.village").
The rest response I am locking for:
{
"user": {
"prename": "Joe",
"address" : {
"village": "NY"
}
}, "validationInfos": [{
"name": "prename",
"required": true,
"maxlenght": 10
}, {
"name": "address.village",
"required": false,
"maxlenght": 20
}]
}
In JavaScript I planning to do something like:
for (var i = 0; i < data.validationInfos.length;; i++) {
var element = data.validationInfos;
element.value = eval ("data.user." + element.name);
}
You should use jackson introspection instead of pure java reflection. It will allow you to discover json properties mapped to java fields/methods according to your serialization config.
JavaType userType = mapper.getTypeFactory().constructType(User.class);
BeanDescription introspection =
mapper.getSerializationConfig().introspect(userType);
List<BeanPropertyDefinition> properties = introspection.findProperties();
// do some processing over properties...

json request enum

We have RestWS where need to pass request in JSON format. This request contains different type of values such as String, List, enum etc.
We figured out how need to pass String and List (see below) but not sure how to pass enum in JSON request object.
Sample JSON Request for List and String in request:
{"firstparam":["195","196"],"secondparam":"test"}
First param is List and second param is String. Similarly we need to know how we can pass enum (also in the above request).
Sample enum class:
#XmlType(name = "Type")
#XmlEnum
public enum Type {
#XmlEnumValue("New")
NEW("New"),
#XmlEnumValue("Delete")
DELETE("Delete"),
#XmlEnumValue("Process")
PROCESS("Process");
private final String value;
WorkingStatusType(String v) {
value = v;
}
public String value() {
return value;
}
public static WorkingStatusType fromValue(String v) {
for (WorkingStatusType c: WorkingStatusType.values()) {
if (c.value.equals(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}
This Google JSON style guide might help you.

Categories