I'm create REST api with springFramework. Create products from post api, but rest method does not cast the parameters with TitleCase parameter name.
My Product model:
public class Product extends BaseModel {
private String title;
private String shortDescription;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getShortDescription() {
return shortDescription;
}
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
}
My Product REST Api:
#PostMapping(value = "/product", consumes = {MediaType.APPLICATION_JSON_VALUE})
public ApiResponse Insert(#RequestBody Product model){
ApiResponse response = new ApiResponse();
try{
response.setData(_service.Insert(model));
response.setSuccess(true);
} catch (Exception ex){
response = _service.HandleException(ex);
}
return response;
}
Worked Request Object:
{
"title" : "TEST",
"shortDescription" : "SD",
"longDescription" : "LD"
}
Not Worked Request Object:
{
"Title" : "TEST",
"ShortDescription" : "SD",
"LongDescription" : "LD"
}
I want both options to work. I'm new to Java, so I did not know how to get around to it, so I wanted to ask.
UPDATED
Jackson Config File
#Configuration
#EnableWebMvc
public class JacksonConfiguration {
#Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
return mapper;
}
}
Thanks.
This works fine:
package com.example;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
public class Test {
private ObjectMapper mapper;
public static class A{
private int test;
public int getTest() {
return test;
}
public void setTest(int test) {
this.test = test;
}
}
#Before
public void setUp(){
mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
}
#Test
public void deserialise() throws Exception {
String json = "{\"test\":\"2\"}";
assertThat(mapper.readValue(json, A.class).getTest(), is(2));
}
#Test
public void deserialiseIgnoringCase() throws Exception {
String json = "{\"Test\":\"2\"}";
assertThat(mapper.readValue(json, A.class).getTest(), is(2));
}
}
Product model does not seem to have longDescription field. That might be the reason why deserialisation will fail (as there is no #JsonIgnore) on Product class. Below snippet works fine:
class Product {
private String title;
private String shortDescription;
private String longDescription;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getShortDescription() {
return shortDescription;
}
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
public String getLongDescription() {
return longDescription;
}
public void setLongDescription(String longDescription) {
this.longDescription = longDescription;
}
}
public static void main(String[] args) throws Exception{
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
Product product = mapper.readValue("{\"Title\" : \"TEST\",\"ShortDescription\" : \"SD\",\"LongDescription\" : \"LD\"}", Product.class);
System.out.println(product.getShortDescription());
}
It will throw an Exception if you comment out longDescription.
Related
I need to set a request Payload as (attached image) in rest assured, the images tag has to contain a array of name and job value pair and followed by url string array. I tried using POJO, but I could not replicate the payload exactly.
sample payload
{
"id":1,
"title":"iPhone 9",
"description":"An apple mobile which is nothing like apple",
"price":549,
"images":[
{
"name":"aaa",
"job":"dev"
},
"https://i.dummyjson.com/data/products/1/1.jpg",
"https://i.dummyjson.com/data/products/1/2.jpg"
]
}
The code I tried.
Main class,
public class PostDataWithoutSerial {
pojoimage p1 = new pojoimage();
Images i1=new Images();
List<Images> img = new ArrayList<Images>();
ArrayList<String> url1 = new ArrayList<String>();
#Test
public void postRequestWithoutSerial()
{
p1.setTitle("google");
p1.setDescription("google phone");
p1.setPrice("800");
i1.setName("james");
i1.setJob("watt");
url1.add("aaa");
url1.add("bbb");
i1.setUrl(url1);
img.add(i1);
p1.setImages(img);
given().log().all()
.contentType("application/json")
.body(p1)
.when()
.post("http://localhost:3000/products")
.then()
.statusCode(201);
//validating single value in response
}
}
pojoimage.java class (Getters and setters class)
import java.util.ArrayList;
import java.util.List;
import java.util.List;
public class pojoimage {
public String id;
public String title;
public String description;
public String price;
public List< Images> images;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public List<Images> getImages() {
return images;
}
public void setImages(List<Images> images) {
this.images = images;
}
}
Images. java class
import java.util.ArrayList;
public class Images {
public String name;
public String job;
ArrayList<String> url = new ArrayList<String>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public ArrayList<String> getUrl() {
return url;
}
public void setUrl(ArrayList<String> url1) {
TODO Auto-generated method stub
this.url = url1;
}
}
Since images in your json contains json object and string, then the correct data type to hold both of them is List<Object>. In this solution, I use Map<> to simplify setting data for json object, you can replace by POJO.
import lombok.Data;
#Data
static class PojoImage {
public int id;
public String title;
public String description;
public int price;
public List<Object> images;
}
#Test
public void postRequestWithoutSerial() {
PojoImage pojoImage = new PojoImage();
pojoImage.setId(1);
pojoImage.setTitle("iPhone 9");
pojoImage.setDescription("An apple mobile which is nothing like apple");
pojoImage.setPrice(549);
List<Object> images = new ArrayList<>();
images.add(Map.of("name", "aaa", "job", "dev"));
images.add("https://i.dummyjson.com/data/products/1/1.jpg");
images.add("https://i.dummyjson.com/data/products/1/2.jpg");
pojoImage.setImages(images);
given().log().all()
.contentType("application/json")
.body(pojoImage)
.when()
.post("https://postman-echo.com/post");
}
I am calling Restful service using below code :(Java.net implementation )
StringBuilder responseStrBuilder = new StringBuilder();
try
{
URL url = new URL(restUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(httpRequestMethod);
conn.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
conn.setRequestProperty("Content-Type", "application/json");
if (requestHeaders != null)
{
for (Map.Entry<String, String> entry : requestHeaders.entrySet())
{
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write(urlParameters.getBytes());
os.flush();
os.close();
if (conn.getResponseCode() != 200) {//do something}
br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
while ((output = br.readLine()) != null)
responseStrBuilder.append(output);
Approach 1:
I have below string(JSON String) as my Restful service response , how can I convert it to Java object. Since same(Itm) object is repeated multiple times if I use org.codehaus.jettison.json.JSONObject myObject = new org.codehaus.jettison.json.JSONObject(responseStrBuilder.toString());
It only reads first Itm Object and does not bring list of all item object.
JSON String output from service :
{"Response":{"RID":"04'34'",
"Itm":{"id":{"ab":"1","cd":"12"},"qw":"JK","name":"abcd "},
"Itm":{"id":{"ab":"2","cd":"34},"qw":"JK","name":"asdf "},
"Itm":{"id":{"ab":"3","cd":"12"},"qw":"JK","name":"fghj "}
}}
Approach 2:
I also tried below snippet with correct Java object with setters and getters
ObjectMapper objectMapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MyJavaReponseObject javaObj = mapper.readValue(json, MyJavaReponseObject.class);
This approach also reads only one object of Itm and not all the object as its not coming in array format in JSON string. Is there any better way of getting all the object(Itm) mapped to single List of Object in java pojo ?
You can use the List class in your response object, if you should parse that json string itself.
I have a ReponseJSON class with json objects, one Response and three Itms
static class ReponseJSON {
private Response Response;
#JsonProperty("Response")
public Response getResponse() {
return Response;
}
public void setResponse(Response Response) {
this.Response = Response;
}
static class Response {
private String rid;
private Itm Itm;
private List<Itm> listItm = new ArrayList<Itm>();
public Itm getItm() {
return Itm;
}
#JsonProperty("Itm")
public void setItm(Itm Itm) {
this.Itm = Itm;
listItm.add(Itm);
}
public String getRID() {
return rid;
}
public List<Itm> getItms() {
return listItm;
}
#JsonProperty("RID")
public void setRID(String rid) {
this.rid = rid;
}
static class Itm {
private Id id;
private String qw, name;
public String getQw() {
return qw;
}
public void setQw(String qw) {
this.qw = qw;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Id getId() {
return id;
}
public void setId(Id id) {
this.id = id;
}
static class Id {
private String ab, cd;
public String getCd() {
return cd;
}
public void setCd(String cd) {
this.cd = cd;
}
public String getAb() {
return ab;
}
public void setAb(String ab) {
this.ab = ab;
}
}
}
}
}
In a Response class, I have a list class and save a Itm object whenever object mapper call this class.
static class Response {
... skip ..
private List<Itm> listItm = new ArrayList<Itm>();
... skip ..
#JsonProperty("Itm")
public void setItm(Itm Itm) {
this.Itm = Itm;
listItm.add(Itm);
}
}
Check the full source code as follows.
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonParserTest {
static class ReponseJSON {
private Response Response;
#JsonProperty("Response")
public Response getResponse() {
return Response;
}
public void setResponse(Response Response) {
this.Response = Response;
}
static class Response {
private String rid;
private Itm Itm;
private List<Itm> listItm = new ArrayList<Itm>();
public Itm getItm() {
return Itm;
}
#JsonProperty("Itm")
public void setItm(Itm Itm) {
this.Itm = Itm;
listItm.add(Itm);
}
public String getRID() {
return rid;
}
public List<Itm> getItms() {
return listItm;
}
#JsonProperty("RID")
public void setRID(String rid) {
this.rid = rid;
}
static class Itm {
private Id id;
private String qw, name;
public String getQw() {
return qw;
}
public void setQw(String qw) {
this.qw = qw;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Id getId() {
return id;
}
public void setId(Id id) {
this.id = id;
}
static class Id {
private String ab, cd;
public String getCd() {
return cd;
}
public void setCd(String cd) {
this.cd = cd;
}
public String getAb() {
return ab;
}
public void setAb(String ab) {
this.ab = ab;
}
}
}
}
}
public static void main(String[] args) {
String responseJson =
"{\"Response\":{\"RID\":\"04'34'\","
+ "\"Itm\":{\"id\":{\"ab\":\"1\",\"cd\":\"12\"},\"qw\":\"JK\",\"name\":\"abcd\"}"
+ ",\"Itm\":{\"id\":{\"ab\":\"2\",\"cd\":\"34\"},\"qw\":\"JK\",\"name\":\"asdf\"}"
+ ",\"Itm\":{\"id\":{\"ab\":\"3\",\"cd\":\"12\"},\"qw\":\"JK\",\"name\":\"fghj\"}"
+ "}} ";
ObjectMapper mapper = new ObjectMapper();
ReponseJSON responseObj = null;
try {
responseObj = mapper.readValue(responseJson, ReponseJSON.class);
ReponseJSON.Response response = responseObj.getResponse();
for(int i = 0; i < response.getItms().size(); i++)
{
ReponseJSON.Response.Itm item = response.getItms().get(i);
System.out.println(item.getId().getAb());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
The version of my jackson mapper is 2.9.1.
You check the main method of the source, because the JSON string you prepared is invalid as coddemonkey mentioned.
Have a good day.
Make your json response looks something similar to this
{"Response":{"RID":"04'34'",
"Itms":[{"id":{"ab":"1","cd":"12"},"qw":"JK","name":"abcd "},
{"id":{"ab":"2","cd":"34"},"qw":"JK","name":"asdf "},
{"id":{"ab":"3","cd":"12"},"qw":"JK","name":"fghj "}]
}}
then, use org.json jar to parse the string to jsonObject
JSONObject jsonObject=new JSONObject(responseString);
This is one type of solution, if you can't change the response as mentioned above then you have to manually parse the string(using java bean) there is no other option available.
These are my classes.
Class TypeC {
int var1;
HashMap<String,String>var2;
ArrayList<TypeC> var3;
}
Class TypeB {
TypeC var1;
}
Class TypeA {
Long var1;
TypeB var2;
}
I want to create object of TypeC and then convert it into a corresponding JSON object (complex JSON).
I tried the following but it doesnt work.
TypeC obj = new TypeC();
JSONObject TypeCJSON=new JSONObject(obj);
A full example of data binding using 'com.fasterxml.jackson.databind.ObjectMapper' :
package spring.exos;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args){
final Computer computer = new Computer();
computer.setBrand("Toshiba");
computer.setModel("TSB I7-SSD");
computer.setSpecs(new Specs(new Integer(256), new Integer(8), new Double(2.4)));
final ObjectMapper mapper = new ObjectMapper();
try {
System.out.println(mapper.writeValueAsString(computer));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
public static class Computer{
private String brand;
private String model;
private Specs specs;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public Specs getSpecs() {
return specs;
}
public void setSpecs(Specs specs) {
this.specs = specs;
}
}
public static class Specs {
private Integer hdd;
private Integer memory;
private Double cpu;
public Specs(Integer hdd, Integer memory, Double cpu) {
super();
this.hdd = hdd;
this.memory = memory;
this.cpu = cpu;
}
public Integer getHdd() {
return hdd;
}
public void setHdd(Integer hdd) {
this.hdd = hdd;
}
public Integer getMemory() {
return this.memory;
}
public void setMemory(Integer memory) {
this.memory = memory;
}
public Double getCpu() {
return cpu;
}
public void setCpu(Double cpu) {
this.cpu = cpu;
}
}
}
The output is :
{"brand":"Toshiba","model":"TSB I7-SSD","specs":{"hdd":256,"memory":8,"cpu":2.4}}
You need to have a dependency to:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.1-1</version>
</dependency>
if you are willing to use another library, using Gson https://github.com/google/gson you just need to do this:
String json = new Gson().toJson(object);
I have this json response from a server.
{"session_key":"thekey","expires_in":300,"environment":"exttest","country":"SE","private_feed":{"hostname":"priv.api.test.nordnet.se","port":443,"encrypted":true},"public_feed":{"hostname":"pub.api.test.nordnet.se","port":443,"encrypted":true}}
The top level info is parsed fine into the below class. But how do I populate the list of server info?
The code
Response response = baseResource.path("login").queryParam("service", "NEXTAPI")
.queryParam("auth", authParam).request(responseType).post(null);
System.out.println(response);
SessionInfo ses = response.readEntity(SessionInfo.class);
public class SessionInfo {
public String session_key;
public String environment;
public int expires_in;
public String country;
List<ServerInfo> serverInfo = new ArrayList<ServerInfo>();
}
public class ServerInfo {
public String hostname;
public int port;
public boolean encrypted;
}
This works, but I would hope there is a way to convert it in one step since there might be more nested levels in other responses.
ObjectMapper mapper = new ObjectMapper();
ObjectNode json = response.readEntity(ObjectNode.class);
SessionInfo ses = mapper.treeToValue(json, SessionInfo.class);
ServerInfo s1 = mapper.treeToValue(json.get("private_feed"), ServerInfo.class);
ServerInfo s2 = mapper.treeToValue(json.get("public_feed"), ServerInfo.class);
ses.serverInfo.add(s1);
ses.serverInfo.add(s2);
I tried using Jackson, and was able to build the JSON object in one liner. Probably what you are looking for.
import java.io.IOException;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
public class JackSontest {
public static void main(String[] args){
String jstr = "{\"session_key\":\"thekey\",\"expires_in\":300,\"environment\":\"exttest\",\"country\":\"SE\",\"private_feed\":{\"hostname\":\"priv.api.test.nordnet.se\",\"port\":443,\"encrypted\":true},\"public_feed\":{\"hostname\":\"pub.api.test.nordnet.se\",\"port\":443,\"encrypted\":true}}";
System.out.println("Calling jsonToObject...");
ObjectMapper objectMapper = new ObjectMapper();
try {
SessionInfo info = objectMapper.readValue(jstr, SessionInfo.class);
System.out.println("Session_key:- " + info.getSession_key());
System.out.println("Expires_in:- " + info.getExpires_in());
System.out.println("Environment:- " + info.getEnvironment());
System.out.println("Private Feed:- " + info.getPrivate_feed().getHostname());
System.out.println("Public Feed:- " + info.getPublic_feed().getHostname());
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SessionInfo {
private String session_key;
private String environment;
private int expires_in;
public String getSession_key() {
return session_key;
}
public void setSession_key(String session_key) {
this.session_key = session_key;
}
public String getEnvironment() {
return environment;
}
public void setEnvironment(String environment) {
this.environment = environment;
}
public int getExpires_in() {
return expires_in;
}
public void setExpires_in(int expires_in) {
this.expires_in = expires_in;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
private String country;
private Feed private_feed;
public Feed getPrivate_feed() {
return private_feed;
}
#JsonProperty("private_feed")
public void setPrivate_feed(Feed private_feed) {
this.private_feed = private_feed;
}
private Feed public_feed;
public Feed getPublic_feed() {
return public_feed;
}
#JsonProperty("public_feed")
public void setPublic_feed(Feed public_feed) {
this.public_feed = private_feed;
}
}
class Feed {
private String hostname;
private int port;
private boolean encrypted;
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public boolean isEncrypted() {
return encrypted;
}
public void setEncrypted(boolean encrypted) {
this.encrypted = encrypted;
}
}
Output:
Calling jsonToObject...
Session_key:- thekey
Expires_in:- 300
Environment:- exttest
Private Feed:- priv.api.test.nordnet.se
Public Feed:- priv.api.test.nordnet.se
have you tried Gson:
public class Employee
{
private Integer id;
private String firstName;
private String lastName;
private List<String> roles;
private Department department; //Department reference
//Other setters and getters
}
class DepartmentInstanceCreator implements InstanceCreator<Department> {
public Department createInstance(Type type)
{
return new Department("None");
}
}
//Now <strong>use the above InstanceCreator</strong> as below
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Department.class, new DepartmentInstanceCreator());
Gson gson = gsonBuilder.create();
System.out.println(
gson.fromJson("{'id':1,'firstName':'Lokesh','lastName':'Gupta','roles':['ADMIN','MANAGER'],'department':{'deptName':'Finance'}}",
Employee.class));
Output:
Employee [id=1, firstName=Lokesh, lastName=Gupta, roles=[ADMIN, MANAGER], department=Department [deptName=Finance]]
source
I am using XStream Library.
Link of xml service
http://webservices.nextbus.com/service/publicXMLFeed?command=routeConfig&a=ttc&r=54
My Classes......
package com.example.myjakcontest;
import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamAlias;
public class Body {
#XStreamAlias("copyright")
private String _copyright;
private Route route;
public String get_copyright() {
return this._copyright;
}
public void set_copyright(String _copyright) {
this._copyright = _copyright;
}
public Route getRoute() {
return this.route;
}
public void setRoute(Route route) {
this.route = route;
}
}
package com.example.my**jakcontest;**
import java.util.List;
public class Direction{
private String _branch;
private String _name;
private String _tag;
private String _title;
private String _useForUI;
private List<Stop> stop;
public String get_branch(){
return this._branch;
}
public void set_branch(String _branch){
this._branch = _branch;
}
public String get_name(){
return this._name;
}
public void set_name(String _name){
this._name = _name;
}
public String get_tag(){
return this._tag;
}
public void set_tag(String _tag){
this._tag = _tag;
}
public String get_title(){
return this._title;
}
public void set_title(String _title){
this._title = _title;
}
public String get_useForUI(){
return this._useForUI;
}
public void set_useForUI(String _useForUI){
this._useForUI = _useForUI;
}
public List<Stop> getStop(){
return this.stop;
}
public void setStop(List<Stop> stop){
this.stop = stop;
}
}
Async Task
XStream x = new XStream();
x.alias("body", Body.class);
x.alias("stop", Stop.class);
x.alias("route", Route.class);
x.alias("direction", Direction.class);
x.alias("path", Path.class);
x.alias("point", Point.class);
x.addImplicitCollection(Route.class, "stop");
x.addImplicitCollection(Route.class, "direction");
x.addImplicitCollection(Route.class, "path");
x.addImplicitCollection(Direction.class, "stop");
x.addImplicitCollection(Path.class, "point");
Body object = (Body) x.fromXML(httpResponse.getEntity()
.getContent());
// Function converts XML to String
String xml = convertStreamToString(httpResponse.getEntity()
.getContent());
Body b = (Body) x.fromXML(xml);
I have all the classes but in object "b" i am getting null.
Try JAXB .It s a standard way of doing it...!
refer the link www.javatpoint.com/jaxb-unmarshalling-example