I'm trying to get some data from other API and I need to get StatusCode from JSON object but I'm getting null object.
I was trying to create new class with StatusCode variable but I'm getting null.
I'm trying to get this data :
Data(data=[{"Number":"20450143160505","DateCreated":"11-06-2019 10:14:27","DocumentWeight":0.5,"CheckWeight":0,"SumBeforeCheckWeight":0,"PayerType":"Recipient","RecipientFullName":"","RecipientDateTime":"","ScheduledDeliveryDate":"12-06-2019","PaymentMethod":"Cash","CargoDescriptionString":"","CargoType":"Parcel","CitySender":"Сокільники","CityRecipient":"Київ","WarehouseRecipient":"Відділення №150 (до 30 кг): вул. Антоновича, 43 (м.\"Олімпійська\")","CounterpartyType":"PrivatePerson","Redelivery":1,"RedeliverySum":"","RedeliveryNum":"","RedeliveryPayer":"","AfterpaymentOnGoodsCost":"","ServiceType":"WarehouseWarehouse","UndeliveryReasonsSubtypeDescription":"","WarehouseRecipientNumber":150,"LastCreatedOnTheBasisNumber":"","LastCreatedOnTheBasisDocumentType":"","LastCreatedOnTheBasisPayerType":"","LastCreatedOnTheBasisDateTime":"","LastTransactionStatusGM":"","LastTransactionDateTimeGM":"","WarehouseRecipientInternetAddressRef":"916c7c93-8460-11e4-acce-0050568002cf","MarketplacePartnerToken":"","DateScan":"12:23 12.06.2019","ClientBarcode":"","SenderAddress":"","RecipientAddress":"","CounterpartySenderDescription":"","CounterpartyRecipientDescription":"","CounterpartySenderType":"Organization","PaymentStatus":"","PaymentStatusDate":"","AmountToPay":"","AmountPaid":"","WarehouseRecipientRef":"916c7c94-8460-11e4-acce-0050568002cf","DocumentCost":40,"AnnouncedPrice":"","OwnerDocumentNumber":"","DateFirstDayStorage":"2019-06-21","InternationalDeliveryType":"","DaysStorageCargo":"","RecipientWarehouseTypeRef":"841339c7-591a-42e2-8233-7a0a00f0ed6f","StorageAmount":"","StoragePrice":"","VolumeWeight":"0.50","SeatsAmount":"1","OwnerDocumentType":"","ActualDeliveryDate":"2019-06-12 12:23:22","DateReturnCargo":"","CardMaskedNumber":"","Status":"Прибув у відділення","StatusCode":"7","RefEW":"8ed817ef-8c18-11e9-91ff-0025b501a04b","RedeliveryPaymentCardRef":"","RedeliveryPaymentCardDescription":"","CreatedOnTheBasis":"","DatePayedKeeping":"2019-06-21 00:00:00","OnlineCreditStatusCode":"","OnlineCreditStatus":""}])
Method to get data :
RestTemplate restTemplate = new RestTemplate();
Data string = restTemplate.postForObject(blalba,blabla,Data.class)
And my class
public class Data {
#JsonProperty("data")
private JsonNode data;
//get set
}
There are a few ways to achieve it:
Using a Map<String, Object>
You could read the response payload as a Map<String, Object>:
ParameterizedTypeReference<HashMap<String, Object>> responseType =
new ParameterizedTypeReference<HashMap<String, Object>>() {};
Map<String, Object> responsePayload =
restTemplate.exchange(purchaseRequestDetailsEndpoint, HttpMethod.POST,
new HttpEntity<>(requestPayload), responseType);
String statusCode = responsePayload.get("StatusCode");
Mapping only the properties you need
Define a class mapping the properties you need:
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class ResponsePayload {
#JsonProperty("StatusCode")
private String statusCode;
}
And read the response payload using the class defined above:
ResponsePayload responsePayload =
restTemplate.postForObject(uri, request, ResponsePayload.class);
String statusCode = responsePayload.getStatusCode();
Alternatively you could map the properties you need and store the rest in a map:
#Data
public class ResponsePayload {
#JsonProperty("StatusCode")
private String statusCode;
#JsonAnySetter
private Map<String, Object> properties = new HashMap<>();
#JsonIgnore
public Object get(String key) {
return properties.get(key);
}
}
Related
I need to consume and parse incoming json from a CRM system in my code. I used RestTemplate to do it. So the response from the CRM system looks like below.
{ "GvyArEFkg6JX6wI": {
"entityId": "GvyArEFkg6JX6wI",
"mergePolicy": {
"id": "9245a39d-fe1a-4b33-acab-9bc5cbabf37c"
}
}
}
Now the problem is the property name ("GvyArEFkg6JX6wI" in this case) in dynamic and in the next response it would be another string. In this case, how can I parse this json as this is not fixed? I tried using jsonGetter but it only wraps it around another block and still does not resolve the problem of parsing the response.
AdobeResponseDto.class
#Builder
#ToString
#AllArgsConstructor
#JsonInclude(JsonInclude.Include.NON_NULL)
#NoArgsConstructor
public class AdobeResponseDto {
public Map<String, AdobeResponseFinal> adobeResponseWrapper = new HashMap<>();
#JsonAnySetter
public void setAdobeResponseWrapper(String name, AdobeResponseFinal value) {
adobeResponseWrapper.put(name, value);
}
#JsonAnyGetter
public Map<String, AdobeResponseFinal> getAdobeResponseWrapper() {
return adobeResponseWrapper;
}
}
AdobeResponseFinal.class
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class AdobeResponseFinal {
public String entityId;
public MergePolicy mergePolicy;
}
I am calling the service like this:
final ResponseEntity<AdobeResponseDto> finalResponse;
finalResponse = aepClient.exchange(uri,HttpMethod.GET,entity,AdobeResponseDto.class);
final AdobeResponseDto body = finalResponse.getBody();
if(ObjectUtils.isNotEmpty(body)){
return body;
}
But in this way, the response I am getting is
{
"adobeResponseWrapper": {
"GvyArEFkg6JX6wI": {
"entityId": "GvyArEFkg6JX6wI",
"mergePolicy": {
"id": "9245a39d-fe1a-4b33-acab-9bc5cbabf37c"
}
}
If you just want to get the value of dynamic field name (e.g., "GvyArEFkg6JX6wI" in your case), you can just deserialize the response body to a Map and then traverse its value as follows:
ResponseEntity<String> finalResponse = aepClient.exchange(uri, HttpMethod.GET, entity, String.class);
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> result = objectMapper.readValue(finalResponse.getBody(), Map.class);
result.values().forEach(System.out::println);
Console output:
{entityId=GvyArEFkg6JX6wI, mergePolicy={id=9245a39d-fe1a-4b33-acab-9bc5cbabf37c}}
And if you want to deserialize the response body to your DTO (I assume that there is only ONE root-level property), you can modify the DTO like:
public class AdobeResponseDto {
private AdobeResponseFinal adobeResponseFinal;
#JsonAnySetter
public void setAdobeResponseFinal(String name, AdobeResponseFinal value) {
adobeResponseFinal = value;
}
#JsonAnyGetter
public AdobeResponseFinal getAdobeResponseFinal() {
return adobeResponseFinal;
}
}
Then you can get similar result as follows:
ResponseEntity<String> finalResponse = aepClient.exchange(uri, HttpMethod.GET, entity, String.class);
AdobeResponseDto adobeResponseDto = objectMapper.readValue(finalResponse.getBody(), AdobeResponseDto.class);
System.out.println(adobeResponseDto.getAdobeResponseFinal().toString());
Console output:
AdobeResponseFinal{entityId='GvyArEFkg6JX6wI', mergePolicy=MergePolicy{id='9245a39d-fe1a-4b33-acab-9bc5cbabf37c'}}
I have a JSON as follows
{
"1.2.3.4": "domain1.com",
"1.2.3.5": "domain2.com"
}
And a model
public class DnsLookup {
#Getter #Setter private Map<String, String> entry;
}
And retrofit query interface
#GET("/dns/")
Call<DnsLookup> getDns(#QueryMap Map<String, String> params);
When I make the query, I get null in dns.
Call<DnsLookup> call = service.getDns(queryMap);
Response<DnsLookup> response;
response = call.execute();
var dns = response.body();
Actually the original JSON is
{
"1.2.3.4": [
"domain1.com", "domain1-1.com"
],
"1.2.3.5": [
"domain2.com"
]
}
And I have tried the following model to only get null. Since the following didn't work, I broke the problem to just key-value pairs. To my surprise, the simple map also didn't work.
public class DnsLookup {
#Getter #Setter private Map<String, List<String>> entry;
}
Am I doing a noob mistake?
Use:
#GET("/dns/")
Call<Map<String, List<String>>> getDns(#QueryMap Map<String, String> params);
Instead of:
#GET("/dns/")
Call<DnsLookup> getDns(#QueryMap Map<String, String> params);
I have created an API with a Map<String, Integer> parameter, like this:
#RequestMapping(value = "upload", method = RequestMethod.POST)
public ResponseEntity<String> handleContactsFileUpload(#RequestParam("file") MultipartFile file,
#RequestParam("name") String name,
#RequestParam("campaignAppItemId") Long campaignAppItemId,
#RequestParam("fileColumnHeaders") Map<String,Integer> fileColumnHeaders) throws Exception {
if (file == null)
return new ResponseEntity<>("No file uploaded", HttpStatus.BAD_REQUEST);
contactService.handleContactsFile(file, name, campaignAppItemId,fileColumnHeaders);
return new ResponseEntity<>("File uploaded successfully", HttpStatus.OK);
}
I am trying to call this via Postman:
I passed the fileColumnHeaders inside Body->Form Data as in the screenshot.
Then I got a message like this in Postman:
Failed to convert value of type 'java.lang.String' to required type 'java.util.Map'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Map': no matching editors or conversion strategy found.
Anybody know why this message came ?
How can we pass a map as a parameter in Rest API request?
How can we pass a map through Postman?
You could use #RequestBody instead of #RequestParam for Maps and other non trivial data types and objects - this way spring will map the JSON representing your map parameter to a domain object, which is then serializable and can be converted to a java object.
... Or simply create a converter:
#Component
#RequiredArgsConstructor
public class StringToMapConverter implements Converter<String, Map<String, Object>> {
private final ObjectMapper objectMapper;
#Override
public Map<String, Object> convert(String source) {
try {
return objectMapper.readValue(source, new TypeReference<Map<String, String>>() {
});
} catch (final IOException e) {
return null;
}
}
}
Firstly, you create DTO object to get all data from your request.
public class FormDataDTO {
private MultipartFile file;
private String name;
private Long campaignAppItemId;
private Map<String,Integer> fileColumnHeaders;
// getters, setters
}
Secondly, you can map FormDataDTO from your request without any annotation:
#RequestMapping(value = "upload", method = RequestMethod.POST)
public ResponseEntity<String> handleContactsFileUpload(FormDataDTO formDataDTO){
// your logic code here
}
Finally, form-data in your request will be:
I think this could work:
#RequestMapping(value = "upload/{fileColumnHeaders}", method = RequestMethod.POST)
public ResponseEntity<String> handleContactsFileUpload(#RequestParam("file") MultipartFile file,
#RequestParam("name") String name,
#RequestParam("campaignAppItemId") Long campaignAppItemId,
#MatrixVariable Map<String,Integer> fileColumnHeaders) throws Exception {
if (file == null)
return new ResponseEntity<>("No file uploaded", HttpStatus.BAD_REQUEST);
contactService.handleContactsFile(file, name, campaignAppItemId,fileColumnHeaders);
return new ResponseEntity<>("File uploaded successfully", HttpStatus.OK);
}
Put all other parameters into the body, but add the fileColumnHeaders to the URL like this:
/upload/firstName=1;lastName=2;address=3;phone=4
You will also need this extra configuration:
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
Objective
I'd like to use JSON-RPC to send this on the clientside:
{"jsonrpc":"2.0","method":"RegisterValues","params":[["Planets","Stars"]],"id":2}
My Attempt
Using Resty-GWT:
public interface testService extends RestService {
#Produces("application/json")
#POST
public void myCall(Params myparams, MethodCallback<Response> callback );
public class Params {
String jsonrpc = "2.0";
String method;
//String[] params;
Map<String, String> params;
int id;
public void setId(int id){
this.id = id;
}
public void setMethod(String method){
this.method = method;
}
}
public void setParams(Map<String, String> params){
this.params = params;
}
}
When I call upon the Params object in another class (to set up the call), doing something like this:
Map<Integer, String> myParams = new HashMap<Integer, String>();
myParams.put(0, "Planets");
myParams.setParams(myParams);
Obviously this then sends it like:
{"jsonrpc":"2.0", "method":"RegisterValues", "params":{"0":"Planets"}, "id":0}
I can't figure out how to get those magic: [["Planets"]]
I tried using a String[] but this gives me the result: ["Planets"]
String[][] gives the error that it isn't supported yet.
Horrible Hack
If I pass a String in my testService as:
String myparams = "{\"jsonrpc\":\"2.0\",\"method\":\"RegisterValues\",\"params\":[[\"FPlanets\"]],\"id\":2}";
It works but obviously this is horrible.
I tried using GSON to encode the POJO, but GWT doesn't allow reflections. I tried using thetransactioncompany to parse the object into a 'String' but couldn't figure out the <inherits> I needed in my gwt.xml file.
Any thoughts?
Try this one
List<List<String>> params;
instead of
Map<String, String> params;
in your Params POJO class.
Read my post here about How to create a POJO class structure from an JSON string.
below JSON string
"params":[["Planets","Stars"]]
represents a List<List<String>> where "params" is a variable name in your POJO.
POJO:
class Params implements Serializable {
private String jsonrpc;
private String method;
private int id;
private List<List<String>> params;
...
//getter/setter
//default constructor
}
Try this one at server side
String myparams = "{\"jsonrpc\":\"2.0\",\"method\":\"RegisterValues\",\"params\":[[\"FPlanets\"]],\"id\":2}";
Params params=gson.fromJson(myparams,Params.class);
System.out.println(params.params+"-"+params.id);
Send the Params object back to client.
I am using Spring framework to get JSON data from a local server into an Object via Http GET.
But the object is always null(no data stored)
I have double checked the server and it is working fine
the server returns {"Propid":"61", "Proptitle":"3 bhk villa","Propdealer":"admin"}
I have added the Jackson Libraries
I have used StringHttpMessageConverter and it returns the JSON string {"Propid":"61", "Proptitle":"3 bhk villa","Propdealer":"admin"}
Throws exception:Could not extract response: no suitable HttpMessageConverter found for response type [com.aditya.master.classes.Prop] and content type [text/html;charset=UTF-8]
Here is the code that parses the JSON response
URI targetUrl= UriComponentsBuilder.fromUriString("http://192.168.1.9/PinSpace/oauth/")
.path("request_access/")
.queryParam("query", "get_property")
.queryParam("access_token", auth_code)
.queryParam("prop_id", "61")
.build()
.toUri();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAccept(Collections.singletonList(new MediaType("application", "json")));
HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders);
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<Prop> responseEntity = restTemplate.exchange(targetUrl, HttpMethod.GET, requestEntity, Prop.class);
Prop result = responseEntity.getBody();
Here is the Prop class
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
#JsonIgnoreProperties(ignoreUnknown = true)
public class Prop {
#JsonProperty
private String Propid, Proptitle, Propdealer;
public String getPropid() {
return Propid;
}
public void setPropid(String propid) {
Propid = propid;
}
public String getProptitle() {
return Proptitle;
}
public void setProptitle(String proptitle) {
Proptitle = proptitle;
}
public String getPropdealer() {
return Propdealer;
}
public void setPropdealer(String propdealer) {
Propdealer = propdealer;
}
}
Please suggest a solution
Thanks!
You can test deserialization with follow code:
ObjectMapper objectMapper = new ObjectMapper();
String content = "{\"Propid\":\"61\", \"Proptitle\":\"3 bhk villa\",\"Propdealer\":\"admin\"}";
objectMapper.readValue(content , Prop.class);
This trows exeception
org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "Propid"
which means that fields naming in your class is incorrect or you need to point correct names in #JsonProperty annotation
I suggest you to use next structure:
public class Prop {
private String propid;
private String proptitle;
private String propdealer;
public String getPropid() {
return propid;
}
#JsonProperty("Propid")
public void setPropid(String propid) {
this.propid = propid;
}
public String getProptitle() {
return proptitle;
}
#JsonProperty("Proptitle")
public void setProptitle(String proptitle) {
this.proptitle = proptitle;
}
public String getPropdealer() {
return propdealer;
}
#JsonProperty("Propdealer")
public void setPropdealer(String propdealer) {
this.propdealer = propdealer;
}
}
There is a way to get this to work with an incorrect MIME type as well: you just need to add "text/html" to your list of accepted media types. like so:
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
List<MediaType> mediaTypeList = new ArrayList<MediaType>();
//...
mediaTypeList.addAll( jsonConverter.getSupportedMediaTypes() );
mediaTypeList.add(MediaType.TEXT_HTML);
jsonConverter.setSupportedMediaTypes(mediaTypeList);
this will be quite handy if you don't have access to the server.
NOTE
there's probably a less verbose way to do this, but I'm just getting back to Java after 10 years in other environs :-)