How can I keep the original case of the keys when writing the object to json?
POJO-Class:
public class LeadRequest
{
private String AccountName;
private String AccountAlias;
private String BPID;
private String CustomerType;
private String Email;
private String LocationType;
private String APRID;
private String APRDistributorName;
private String EngagedwithRAOrDistributor;
public String getBPID()
{
return BPID;
}
public void setBPID(final String bPID)
{
BPID = bPID;
}
public String getEngagedwithRAOrDistributor()
{
return EngagedwithRAOrDistributor;
}
public void setEngagedwithRAOrDistributor(final String engagedwithRAOrDistributor)
{
EngagedwithRAOrDistributor = engagedwithRAOrDistributor;
}
}
Service-class:
public void submitLeadRequest(final LeadRequest lead)
{
try
{
final String endPoint = Config.getParameter(ServicesConstants.API_URL);
final HttpPost request = new HttpPost(endPoint);
request.addHeader(ServicesConstants.CONTENT_TYPE, ServicesConstants.APPLICATION_JSON);
request.addHeader(ServicesConstants.CLIENT_ID, Config.getParameter(ServicesConstants.CLIENT_ID));
request.addHeader(ServicesConstants.CLIENT_SECRET, Config.getParameter(ServicesConstants.CLIENT_SECRET));
final ObjectMapper mapper = new ObjectMapper();
final String jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(lead);
final StringEntity entity = new StringEntity(jsonString);
request.setEntity(entity);
final RequestConfig requestConfig = getRequestConfig(API_TIMEOUT_LONG);
final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
CloseableHttpResponse response = client.execute(request);
}
}
Currently the Post Request json generated is:
{
"accountAlias" : "No Account Alias",
"accountName" : "REI AUTOMATION INC",
"customerType" : "OEM",
"aprid" : "002",
"bpid" : "0099105850",
"locationType" : "Research & Development",
"email" : "john.smith#jefftestaccount.com",
"engagedwithRAOrDistributor" : "",
"aprdistributorName" : "002-CED Royal Industrial Elec"
}
But the post request is failing giving HTTP/1.1 500 Server Error because of case sensitive keys in request json for the system being called
Therefore, the desired Request Json is:
If you are using com.fasterxml.jackson.databind.ObjectMapper, you can specify final name for each field using com.fasterxml.jackson.annotation.JsonProperty for example:
#JsonProperty("AccountName")
private String AccountName;
Or you can “tell” to your mapper to use fields instead of getters for creating a final JSON. In order to do so you can just configure your mapper class as follows:
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
Related
I'm trying to consume a given API that returns a body response like this:
"access_token": "xkeo94s4qviHSTDIuTCbgRQSeNfrrMamiCN0w6wu",
"token_type": "Bearer",
"expires_in": 9600,
"refresh_token": "PpF0LfLPmdsm9FJFu4YmDBPENqTwGQIqQjw8MqOP"
So I created the following class:
#JsonIgnoreProperties(ignoreUnknown = true)
public class EHTLToken {
private String access_token;
private String token_type;
private String expires_in;
private String refresh_token;
// getters and setters
I can make a request and get the expected response body with the following code:
#Test
void getTokenTest() {
String uri = "/oauth/access_token";
EHTLClient client = new EHTLClient();
Credenciais credenciais = new Credenciais();
RequestHeadersSpec<?> request = client.getWebClient().method(HttpMethod.POST).uri(uri).bodyValue(credenciais);
String response = request.retrieve().bodyToMono(String.class).block();
System.out.println(response);
}
But when I try to retrieve the response to the EHTLToken.class and get its atributes, the class is is instantiated, but all it's atributes are null. Here's what I'm trying:
#Test
void getTokenTest() {
String uri = "/oauth/access_token";
EHTLClient client = new EHTLClient();
Credenciais credenciais = new Credenciais();
RequestHeadersSpec<?> request = client.getWebClient().method(HttpMethod.POST).uri(uri).bodyValue(credenciais);
EHTLToken response = request.retrieve().bodyToMono(EHTLToken.class).block();
Assert.notNull(response, "Class is null.");
Assert.notNull(response.getAccessToken(), "Token is null.");
}
My second test fails:
java.lang.IllegalArgumentException: Token is null.
at org.springframework.util.Assert.notNull(Assert.java:198)
at br.com.ribeiro.fernando.ehtl.EhtlApplicationTests.getTokenTest(EhtlApplicationTests.java:27)
Am I misunderstanding the concept of bodyToMono()? How can I get atributes from a response body and set to a given class with WebClient please?
Regards.
For anyone having this issue, my problem is that the REST API gives a response like this:
"access_token": "xkeo94s4qviHSTDIuTCbgRQSeNfrrMamiCN0w6wu",
"token_type": "Bearer",
"expires_in": 9600,
"refresh_token": "PpF0LfLPmdsm9FJFu4YmDBPENqTwGQIqQjw8MqOP"
And I created the POJO with the following attributes:
private String access_token;
private String token_type;
private String expires_in;
private String refresh_token;
My test worked when I changed my POJO to this:
#JsonIgnoreProperties(ignoreUnknown = true)
public class EHTLToken {
#JsonProperty("access_token")
private String accessToken;
#JsonProperty("token_type")
private String tokenType;
#JsonProperty("expires_in")
private String expiresIn;
#JsonProperty("refresh_token")
private String refreshToken;
I renamed the attributes as convention, and manually added the json property with the #JsonProperty.
I'm rusty on my Java so I was wondering if anyone could help. I have a Json that comes in from a rest API and I can't seem to get the nested objects to get read, but the fields are there so I'm at a loss.
Here is what my json string looks like (result from String result = response.getEntity(String.class); in wrapper.java)
result = "{"FIRST_NAME":"Test First","LAST_NAME":"Test Last","testAttr":[{"MOTHER_NAME":"Test Mother 1","FATHER_NAME":"Test Father 1"}, {"MOTHER_NAME":"Test Mother 2","FATHER_NAME":"Test Father 2"}]}"
(to better read it)
result = {
"FIRST_NAME": "Test First",
"LAST_NAME": "Test Last",
"testAttr": {
"MOTHER_NAME":"Test Mother 1",
"FATHER_NAME":"Test Father 1"
},
{
"MOTHER_NAME":"Test Mother 2",
"FATHER_NAME":"Test Father 2"
}
}
Using the code below, I was able to get the firstName and lastName without a problem, but I wasn't able to get the nested objects unless I explicitly had them put inside the same with (with the #Serialized, #Exposure). I'm not sure where exactly I've gone wrong since I have no errors with importing :/
Main.java
#GET
#Path("/api/test")
#Produces(MediaType.APPLICATION_JSON)
public Response getAttributrs(#Context HttpServletRequest req) {
ResponseObj responseObj = new ResponseObj();
try {
ResponseObj listOfAttr = wrapper.getAttr();
return Response.ok(listOfAttr).build();
} catch (Exception e) {
wrapper.manageError(e, responseObj) ;
return Response.status(500).entity(responseObj).build();
}
}
Wrapper.java
public ResponseObj getAttr() throws Exception {
Client client = ClientHelper.createClient();
WebResource webResource = client
.resource("https://xxxxxxxxx);
webResource.header("X-METHOD-OVERRIDE", "GET");
webResource.header("content-type", "application/json");
ClientResponse response = webResource.type("application/json").get(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
String result = response.getEntity(String.class);
ResponseObj responseObj = new Gson().fromJson(result, ResponseObj.class);
return responseObj;
}
ResponseObj.java
#SerializedName("testAttr")
#Expose
private List<AttributesClass> testAttributes;
// getters/setters
AttributeClass.java
private TestInnerClass testInnerClass;
#SerializedName("FIRST_NAME")
#Expose
private String firstName;
#SerializedName("LAST_NAME")
#Expose
private String lastName;
//getters/setters
TestInnerClass.java
#SerializedName("MOTHER_NAME")
#Expose
private String mothersName;
#SerializedName("FATHER_NAME")
#Expose
private String fathersName;
//getters/setters
Your model classes should be like below
Class 1
public class ResponseObj {
#SerializedName("FIRST_NAME")
private String fIRSTNAME;
#SerializedName("LAST_NAME")
private String lASTNAME;
#SerializedName("testAttr")
private List<AttributeClass> testAttr = null;
// getter and setter
Class2
public class AttributeClass {
#SerializedName("MOTHER_NAME")
private String mOTHERNAME;
#SerializedName("FATHER_NAME")
private String fATHERNAME;
// getter and setter
two classes are sufficient.
I need to send a json to a web address where this json will be consumed, basically I have a list of Dto's that I need to turn into a Json (with jackson).
Some information must be passed in the header:
timestamp= time, key= blablabla, accesskey= bla bla bla
As I have no experience with spring, i need to know how to do the HTTP request using Spring boot
(is it a post?)
Here's what I've implemented so far:
Student Dto Class
public class StudentDto {
private String name;
private String RM;
private String RG;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRM() {
return RM;
}
public void setRM(String RM) {
this.RM = RM;
}
public String getRG() {
return RG;
}
public void setRG(String RG) {
this.RG = RG;
}
}
Turning my list of students into json
public String convertToJson(List obj) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
String jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
return jsonInString;
}
}
And this is the format json has to leave
{
"table": "student",
"rows":
[
{
"PersonID": 1,
"name": "Name",
"RM": "56656565",
"RG": "8787845-7",
},
{
"PersonID": 2,
"name": "Name",
"RM": "56656565",
"RG": "8787845-7"
}
]
}
below is and example of how to use rest template. You'll want to create a class for the request that has String table; and List<StudentDto> rows; as members
private static void createEmployee()
{
final String uri = "http://localhost:8080/springrestexample/employees";
MultiValueMap<String> headers = new MultiValueMap<>();
//set headers
HttpEntity<EmployeeVO> newEmployee = new HttpEntity<>(new EmployeeVO(-1, "Adam", "Gilly", "test#email.com"),headers);
RestTemplate restTemplate = new RestTemplate();
EmployeeVO result = restTemplate.postForObject( uri, newEmployee, EmployeeVO.class);
System.out.println(result);
}
*edit added headers
*edid look here for json formatting
you will also need to have the id field added to your object
I'm calling a WS using Spring and Resttemplate, and trying to parse the JSON response to a custom object.
WS call snippet:
RestTemplate restTemplate = new RestTemplate();
String wsURL = "https://www.dummyws.com";
String accessToken = "dummyAccessToken"
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.add("Authorization", "Bearer " + accessToken);
headers.add("Accept", "*/*");
MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
HttpEntity<MultiValueMap<String, String>> wsRequest = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<GetPassengersData> wsResponse = restTemplate.exchange(wsURL, HttpMethod.GET, wsRequest, GetPassengersData.class);
GetPassengersData getPassengerData = wsResponse.getBody();
WS response snippet:
{
"data" : [{
"start" : "2018-01-01 00:00:00",
"finish" : "2018-01-01 23:59:59",
"total" : 1076
}
]
}
Custom object definition:
#JsonIgnoreProperties(ignoreUnknown = true)
public static class GetPassengersData implements Serializable
{
private static final long serialVersionUID = 1L;
public GetPassengersData()
{
}
private List<GetPassengersDataItem> data;
public List<GetPassengersDataItem> getData() {
return data;
}
public void setData(List<GetPassengersDataItem> data) {
this.data = data;
}
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class GetPassengersDataItem implements Serializable
{
private static final long serialVersionUID = 1L;
public GetPassengersDataItem()
{
}
private String start;
private String finish;
private double total;
public String getStart() {
return start;
}
public void setStart(String start) {
this.start = start;
}
public String getFinish() {
return finish;
}
public void setFinish(String finish) {
this.finish = finish;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
}
I get the following exception in restTemplate.exchange:
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of double out of START_OBJECT token
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream#552b744a; line: 5, column: 44] (through reference chain: *.GetPassengersData["data"]->*.GetPassengersDataItem["total"]); nested exception is org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of double out of START_OBJECT token
Parsing just String fields works nicely. What I'm missing? What do I need to do to parse a numerical field? I've tried with int, long, double, BigDecimal, getting the same exception error.
Thanks in advance.
I'm not sure but try WS response without "data" node
{
[{
"start" : "2018-01-01 00:00:00",
"finish" : "2018-01-01 23:59:59",
"total" : 1076
}]
}
Or try to mappe to an object with a property List<GetPassengersData> data
I have a REST endpoint as
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getVariables(#QueryParam("_activeonly") #DefaultValue("no") #Nonnull final Active active) {
switch(active){
case yes:
return Response.ok(VariablePresentation.getPresentationVariables(variableManager.getActiveVariables())).build();
case no:
return Response.ok(VariablePresentation.getPresentationVariables(variableManager.getVariables())).build();
}
throw new WebApplicationException(Response.Status.BAD_REQUEST);
}
Which returns JSON of List of VariablePresentation. The VariablePresentaion looks like
#XmlRootElement
public class VariablePresentation {
private final UUID id;
private final String name;
private final VariableType type;
public VariablePresentation(#Nonnull final Variable variable) {
id = variable.getId();
name = variable.getName();
type = variable.getType();
}
public String getId() {
return id.toString();
}
#Nonnull
public String getName() {
return name;
}
#Nonnull
public VariableType getType() {
return type;
}
annotated with JAXB's XmlRoot to return JSON.
My integration test is as following
#Test
public void testGetAllVariablesWithoutQueryParamPass() throws Exception {
final ClientRequest clientCreateRequest = new ClientRequest("http://localhost:9090/variables");
final MultivaluedMap<String, String> formParameters = clientCreateRequest.getFormParameters();
final String name = "testGetAllVariablesWithoutQueryParamPass";
formParameters.putSingle("name", name);
formParameters.putSingle("type", "String");
formParameters.putSingle("units", "units");
formParameters.putSingle("description", "description");
formParameters.putSingle("core", "true");
final ClientResponse<String> clientCreateResponse = clientCreateRequest.post(String.class);
assertEquals(201, clientCreateResponse.getStatus());
}
I want to test the request body which returns the List<VariablePresentation> as String. How can I convert the response body (String) as VariablePresentation Object?
Update
After adding the following
final GenericType<List<VariablePresentation>> typeToken = new GenericType<List<VariablePresentation>>() {
};
final ClientResponse<List<VariablePresentation>> clientCreateResponse = clientCreateRequest.post(typeToken);
assertEquals(201, clientCreateResponse.getStatus());
final List<VariablePresentation> variables = clientCreateResponse.getEntity();
assertNotNull(variables);
assertEquals(1, variables.size());
Its fails with different Error
testGetAllVariablesWithoutQueryParamPass(com.myorg.project.market.integration.TestVariable): Unable to find a MessageBodyReader of content-type application/json and type java.util.List<com.myorg.project.service.presentation.VariablePresentation>
How do I resolve this?
The easiest way I found is to use ClientResponse with Gson
A simple example could be
#Test
public void testGetAllVariablesWithoutQueryParamNoPass() throws Exception {
final ClientRequest clientCreateRequest_var0 = new ClientRequest("http://localhost:9090/variables?_activeonly=no");
final MultivaluedMap<String, String> formParameters = clientCreateRequest_var0.getFormParameters();
final String name0 = "testGetAllVariablesWithoutQueryParamNoPass_0";
formParameters.putSingle("name", name0);
formParameters.putSingle("type", "String");
formParameters.putSingle("units", "units");
formParameters.putSingle("description", "description");
formParameters.putSingle("core", "true");
final ClientResponse<String> clientCreateResponse_var0 = clientCreateRequest_var0.post(String.class);
assertEquals(201, clientCreateResponse_var0.getStatus());
final ClientRequest clientCreateRequest_var1 = new ClientRequest("http://localhost:9090/variables");
final MultivaluedMap<String, String> formParameters1 = clientCreateRequest_var1.getFormParameters();
final String name1 = "testGetAllVariablesWithoutQueryParamNoPass_1";
formParameters1.putSingle("name", name1);
formParameters1.putSingle("type", "String");
formParameters1.putSingle("units", "units");
formParameters1.putSingle("description", "description");
formParameters1.putSingle("core", "true");
final ClientResponse<String> clientCreateResponse_var1 = clientCreateRequest_var1.post(String.class);
assertEquals(201, clientCreateResponse_var1.getStatus());
final ClientRequest clientCreateRequest2 = new ClientRequest("http://localhost:9090/variables");
final ClientResponse<String> clientCreateResponse2 = clientCreateRequest2.get(String.class);
final Gson gson = new Gson();
final Type variableType = new TypeToken<List<VariablePresentation>>() {
}.getType();
List<VariablePresentation> variables = gson.fromJson(clientCreateResponse2.getEntity(), variableType);
assertNotNull(variables);
assertEquals(2, variables.size());
// clean test data
removeTestDataVariableObject(name0);
removeTestDataVariableObject(name1);
}