I have this entity; transferRate is persisted as json format in database :
#Entity
#Data
public class Currency implements Serializable {
#Id
private String currencyIsoCode;
private String currencyIsoNum;
#Convert(converter = JpaConverterJson.class)
private Map<String, Object> transferRate = new HashMap();
}
and in the client project iam using Rest Template to get list of currencies like that
ResponseEntity<List<Currency>> listResponse =
restTemplate.exchange(RestApiConstants.BASE_URL + CurrenciesRestApiConstants.LIST_CURRENCIES,
HttpMethod.GET, null, new ParameterizedTypeReference<>() {
});
currencyList = listResponse.getBody();
But iam getting this error
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `double` from Object value (token `JsonToken.START_OBJECT`)
The class in the client side is like that
#Data
public class Currency implements Serializable {
private String currencyIsoCode;
private String currencyIsoNum;
private Map<String, Object> transferRate;
}
What iam I doing wrong
Thank you in advance
Your field is defined as a Map<String, Object>, so Jackson tries to deserialize the map value as an Object. From JSON point of view, an object is a set of properties in curly braces. This is where the error comes from:
Cannot deserialize value of type `double` from Object value (token `JsonToken.START_OBJECT`)
Apparently on the client side you send a numeric value, so you need to define transferRate with the numeric type, e.g.:
#Convert(converter = JpaConverterJson.class)
private Map<String, Double> transferRate = new HashMap();
And use a similar type on the client:
private Map<String, Double> transferRate;
Related
I am using Spring-boot Application where I am able to connect with Azure App Configuration. But getting the error when I try to read value with content-type application/JSON.
My Java Class
#ConfigurationProperties(prefix = "config")
#Getter
#Setter
public class AppConfigProperties {
private String test;
private Map<String, Map<Integer, List<Integer>>> map;
}
App configuration
key: map
value: {"Cream":{"1":[2,3,4],"2":[25]},"Ice":{"1":[2,3,4],"2":[25]}}
content type = application/json
Error :
Description:
Failed to bind properties under 'config.map' to java.util.Map<java.lang.String, java.util.Map<java.lang.Integer, java.util.List<java.lang.Integer>>>:
Reason: No converter found capable of converting from type [java.lang.String] to type [java.util.Map<java.lang.String, java.util.Map<java.lang.Integer, java.util.List<java.lang.Integer>>>]
Action:
Update your application's configuration
Instead of converting string & integer. You can use as an object.
You can easily convert object into other datatypes.
private Map<String, Map<Integer, List>> map;
You can use
#JsonIgnore
private Map<String, Object> properties = new HashMap<String, Object>();
Refer here
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);
}
}
Hello i got this Json string
{"NexusResource":{"resourceURI":"http://nexus.ad.hrm.se/nexus/service/local/repositories/snapshots/content/se/hrmsoftware/hrm/hrm-release/16.1-SNAPSHOT/","relativePath":"/se/hrmsoftware/hrm/hrm-release/16.1-SNAPSHOT/","text":"16.1-SNAPSHOT","leaf":false,"lastModified":"2018-04-09 12:23:59.0 UTC","sizeOnDisk":-1}}
I want to convert this to an object of a class named NexusResource that looks like this
public class NexusResource {
#JsonProperty("resourceURI") private String resourceURI;
#JsonProperty("relativePath") private String relativePath;
#JsonProperty("text") private String text;
#JsonProperty("leaf") private Boolean leaf;
#JsonProperty("lastModified") private String lastModified;
#JsonProperty("sizeOnDisk") private Integer sizeOnDisk;
#JsonIgnore private Map<String, Object> additionalProperties = new HashMap<>();
}
i try to convert it with an ObjectMapper
ObjectMapper mapper = new ObjectMapper();
NexusResource resource = mapper.readValue(version, NexusResource.class);
were version is the Json string but when i log resource all i get is null (null) even though version got all the data.
You can configure your ObjectMapper to unwrap the root value, in order to de-serialize into your POJO.
E.g.:
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
See API.
You could also work around that by modifying your POJO (see Karol's answer).
Failure to choose either should result in a com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException being thrown, with message: Unrecognized field "NexusResource".
NexusResource is not a root of your JSON but a key. To make your Java mapping work you should define a wrapping type:
public class NexusResources {
#JsonProperty("NexusResource") private NexusResource root;
...
}
and then use it to map:
ObjectMapper mapper = new ObjectMapper();
NexusResources root = mapper.readValue(version, NexusResources.class);
NexusResource resource = root.getRoot();
The problem is that the JSON does not match the class you are trying to parse. Please notice that the JSON has a field called "NexusResource" that has all the other fields. Whereas the class NexusResource.class just has the fields. Two things you can do. Change the JSON to match NexusResource.class, or create a new class that matches the JSON.
1) Change the json to the following.
{"resourceURI":"http://nexus.ad.hrm.se/nexus/service/local/repositories/snapshots/content/se/hrmsoftware/hrm/hrm-release/16.1-SNAPSHOT/","relativePath":"/se/hrmsoftware/hrm/hrm-release/16.1-SNAPSHOT/","text":"16.1-SNAPSHOT","leaf":false,"lastModified":"2018-04-09 12:23:59.0 UTC","sizeOnDisk":-1}
2) Create new class that actually matches your Json.
class NexusResourceJson {
#JsonProperty("NexusResource ")
NexusResource resource;
public NexusResource getResource() {return resource;}
}
ObjectMapper mapper = new ObjectMapper();
NexusResource resource = mapper.readValue(version, NexusResourceJson.class).getResource();
So I'm trying to parse a request that comes in JSON format, but the Google GSON library throws a syntax error.
The request looks like this: {"action":"ProjectCreation", data:{"projectName": "test project"}}.
Which doesn't look like it has a syntax error to me...
Here is the error that GSON gives me:
Exception in thread "main" com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Unterminated object at line 1 column 20 path $.
EDIT:
I fixed the syntax error in the JSON request, it now looks like this {"action":"ProjectCreation", "data":{"projectName": "test project"}}.
GSON is still throwing the same error....
EDIT:
The code responsible for parsing the request looks like this:
private Type type = new TypeToken<Map<String, Object>>(){}.getType();
private String action;
private String responseAction;
private Map<String, String> data;
private Type dataType = new TypeToken<Map<String, String>>(){}.getType();
private Gson gson = new Gson();
private String requestId;
private Client client = new Client("127.0.0.1", 5699);
/**
* Constructor for this class, sets initial parameters
* #param request
* #param _requestId
*/
public ActionThread(String request, String _requestId) {
System.out.println(request);
//Parse the request into a map
Map<String, Object> _request = gson.fromJson(request, type);
//Give action the correct naming convention
action = _request.get("action") + "Request";
responseAction = _request.get("action") + "Response";
//Parse the data into a map
String _data = _request.get("data").toString();
data = gson.fromJson(_data, dataType);
//Set the request id
requestId = _requestId;
}
_request.get("data").toString() is not the JSON representation of your data object. It's the string representation of the inner map you just parsed that is equal to {projectName=test project}.
One easy and quick way to solve this would be to convert your data object into its JSON representation and then parse it again:
Map<String, String> data = gson.fromJson(gson.toJson(_request.get("data")), dataType);
It might be worth to consider having dedicated classes as well, for instance:
class Action {
#SerializedName("action")
String name;
Data data;
}
class Data {
String projectName;
}
and then
Action action = gson.fromJson(request, Action.class);
If you want to have the nested data object as a field directly in the Action class you could also write a custom deserializer.
I'm trying to get the Java class for deserializing this:
API Response
I'm using http://www.jsonschema2pojo.org/ for getting the java classes I need. But with this json response I get this:
public class CatalogueResponse {
#SerializedName("0")
#Expose
private uex.asee.fjrm.multimediapp.api.pojos.catalogue._0 _0;
#SerializedName("1")
#Expose
private uex.asee.fjrm.multimediapp.api.pojos.catalogue._1 _1;
#SerializedName("2")
#Expose
private uex.asee.fjrm.multimediapp.api.pojos.catalogue._2 _2;
#SerializedName("3")
#Expose
private uex.asee.fjrm.multimediapp.api.pojos.catalogue._3 _3;
#SerializedName("4")
#Expose
private uex.asee.fjrm.multimediapp.api.pojos.catalogue._4 _4;
#SerializedName("5")
#Expose
private uex.asee.fjrm.multimediapp.api.pojos.catalogue._5 _5;
...
}
But the number of items of the json is varying, so I can't handle it that way.
I'm using gson annotations by the way.
Any ideas?
Why don't you try using a Map and then serializing it. I would suggest using a TreeMap and adding numbers as keys and values as the Catalogue object. Something like:
Map<Integer, Catalogue> map = new TreeMap<>();
map.put(0, catalogue0);
map.put(1, catalogue1);
...
// Now serialize the map.
This will generate the API response that you require.
To deserialize it using Gson, try the following:
Type mapType = new TypeToken<Map<Integer, Catalogue>>(){}.getType();
Map<Integer, Catalogue> catalogueMap = (Map<Integer, Catalogue>) gson.fromJson(json, mapType);