reading nested json with jackson - MismatchedInputException: Cannot deserialize value - java

stucked at accessing nested json. similar stuff:
[
{
key-value,
key-value
},
{
key-value,
key-value
},
{
key-value,
key-value
}
]
works nicely but when i try:
{
"alfa":{
"id":"foo",
"product":{
"id":"foo1",
"price":"foo2"
}
},
"beta":{
"id":"foo",
"product":{
"id":"foo1",
"price":"foo2"
}
}
}
i get error:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.ArrayList<...
i of course did change structure of classes:
public class Alphabet{
private Purchase purchase;
...
public class Purchase{
private String id;
private Product product;
...
public class Product {
private String id;
private String price;
...
to read it:
ObjectMapper mapper = new ObjectMapper();
InputStream inputStream = new FileInputStream(new File("src/main/json/file.json"));
TypeReference<List<Alphabet>> typeReference = new TypeReference<List<Alphabet>>() {};
List<Alphabet> alphabet= mapper.readValue(inputStream, typeReference);
System.out.println(alphabet);
whats wrong, please?

It seems like the JSON structure you try to read is not a List<Alphabet>, but a Map<String, Purchase>.

Your second json not like list of object. The second json look lik have 2 main objects if so you need class like below.
public class Alphabet{
private Purchase purchase;
private Purchase purchase1;
}
But it not good practice. Use as first josn like list of objects.

Related

JSON to Java object with Random Key

I am trying to convert following JSON to Java object and ending up with UnrecognizedPropertyException.
{
"5214": [{
"name": "sdsds",
"age": "25",
"address": null
},
{
"name": "sdfds",
"age": "26",
"address": null
}]
}
Here "5214" is the random key that I get. I can covert it by modifying JSON little bit. But I want to know whether any possible way to convert the mentioned JSON. I even tried with following snippet taking some reference.
public class SampleTest {
private Map<String, List<EmployeeDetails>> employeeDetails = new HashMap<String, List<EmployeeDetails>>();
public Map<String, List<EmployeeDetails>> getEmployeeDetails() {
return employeeDetails;
}
public void setEmployeeDetails(Map<String, List<EmployeeDetails>> employeeDetails) {
this.employeeDetails = employeeDetails;
}
}
public class EmployeeDetails {
private String name;
private String age;
private String address;
//Getters and Setters
}
Can someone guide me on this?
Use Type Reference (Import Jackson Package for Java)
TypeReference<Map<String, List<EmployeeDetails>>> typeReference = new TypeReference<Map<String, List<EmployeeDetails>>>()
{
};
Map<String, List<EmployeeDetails>> employeeDetails = new ObjectMapper().readValue(jsonString, typeReference);
Check something from that
Maybe:
public class Data {
// String contain the Key, for example: 5214
Map<String, List<EmployeeDetails>> employeeDetails =
new HashMap<String,List<EmployeeDetails>>();
public Data() {
}
#JsonAnyGetter
public Map<String, List<EmployeeDetails>> getEmployeeDetails() {
return employeeDetails;
}
}
I would use custom deserializer with few helper classes. To make the code (matter of opinion I guess) clearer, create the list object:
#SuppressWarnings("serial")
#Getter #Setter
public class EmployeeDetailsList extends ArrayList<EmployeeDetails> {
// this will hold the arbitrary name of list. like 5214
private String name;
}
Then this list seems to be inside an object, say Wrapper:
#Getter
#RequiredArgsConstructor
#JsonDeserialize(using = WrapperDeserializer.class)
public class Wrapper {
private final EmployeeDetailsList employeeDetailsList;
}
So there is annotation #JsonDeserializer that handles deserializing Wrapper. It is not possible to directly deserialize unknown field names to some defined type so we need to use mechanism like this custom deserializer that inspects what is inside Wrapper and determines what to deserialize and how.
And here is how the deserializer works:
public class WrapperDeserializer extends JsonDeserializer<Wrapper> {
private final ObjectMapper om = new ObjectMapper();
#Override
public Wrapper deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
TreeNode node = p.readValueAsTree();
// This is the place for caution. You should somehow know what is the correct node
// Here I happily assume there is just the one and first
String fName = node.fieldNames().next();
EmployeeDetailsList edl = om.readValue(node.get(fName).toString(),
EmployeeDetailsList.class);
edl.setName(fName);
return new Wrapper(edl);
}
}
Please check it carefully it is not perfect in sense finding alwasy the correct node and maybe the instantiation can be done in other ways better. But it shoudl give you a hunch how it could be done.

Converting LinkedHashMap<String,MyClass> to Java Object

How can I convert the JSON string like this:
{ "summary": {
"totalMR":4.599000000000903E12,
"totalMA":1.9174920000386694E11,
"totalQA":5.1111111181E9,
"totalQR":1.000020666115264E11
},
"result": [{},{}],
"success":"true",
"total":49
}
to a Java object. I went through many similar posts and implemented constructors but couldn't find the proper explanation of why I'm unable to De-serialize the JSON.
Am I doing anything wrong?
My Class:
public class expResponse {
private String success;
private String total;
private ArrayList<LinkedHashMap<String,Object>> result;
private LinkedHashMap<String,SummaryResponse> summary;
// Constructor: public expResponse(){}
// Getter and Setter
}
public class SummaryResponse {
private Float totalQR;
private Float totalQA;
private Float totalMR;
private Float totalMA;
public SummaryResponse(){}
// Setter and Getter
}
My Code:
private expResponse processResult(String result) throws IOException{
ObjectMapper objectMapper = new ObjectMapper();
expResponse expResponseObj =
objectMapper.readValue(result, expResponse.class);
return expResponseObj;
The json you posted would not deserialize into a map of SummaryResponse objects, but rather an individual SummaryResponse object. To make your binding work, you would have to have json that looked something like this:
{
...
'summary': {
'summary1': {"totalMR":4.599000000000903E12,"totalMA":1.9174920000386694E11,"totalQA":5.1111111181E9,"totalQR":1.000020666115264E11}
'summary2': {"totalMR":4.599000000000903E12,"totalMA":1.9174920000386694E11,"totalQA":5.1111111181E9,"totalQR":1.000020666115264E11}
}
...
}
Alternatively, if you need to make your Java class conform to the json you provided, you simply need to change the declaration of summary:
private SummaryResponse summary;
Field summary in your json is an object of type SummaryResponse and not a LinkedHashMap.
public class ExpResponse {
private String success;
private String total;
private ArrayList<LinkedHashMap<String,Object>> result;
private Summary summary;
}
I don't think you have a problem in the code. Your input fails because it is not in the correct format. If you try to write the same values from an object with the same values to string you get something like:
{
"success":"true",
"total":"49",
"result":null,
"summary":{
"one_summary":{
"totalQR":2000.0,
"totalQA":1500.0,
"totalMR":1000.0,
"totalMA":500.0
}
}
}
And the major difference is the one summary. This is because summary is a map and maps need a key for each entryset. That means that summary is your map which has a one_summary key.
Is it the SummaryResponse that can't be deserialised?
I guess your attributes should have the same name "totalMR", "totalMA"....
or you should use an annotation JsonProperty(value="totalMR") and so on.

Deserialize dynamic fields with GSON into POJO

I've tried so many ways, but without success to parse this Json to a Java Object using Gson library:
"return":{
"48388":{
"status":"canceled",
"operations":{
},
"created":"138232386",
"price":"12.50000",
"volume":"50.00000000",
"pair":"btc_brl",
"type":"buy"
},
"51714":{
"status":"canceled",
"operations":{
},
"created":"1365465421706",
"price":"1500.00000",
"volume":"0.10000000",
"pair":"btc_brl",
"type":"buy"
},
"48754":{
"status":"canceled",
"operations":{
},
"created":"1383237058",
"price":"600.00000",
"volume":"0.50000000",
"pair":"btc_brl",
"type":"buy"
}
"success":1
}
There is a lot of topics about this, but none of them cover this type of json mapping.
I'm convinced that there is a simple way to do that, any ideas? Thanks!
EDIT:
I'm trying this:
public class Test {
#SerializedName("return")
public Return1 _return;
}
public class Return {
public List<Map<String, Order>> order;
}
EDIT:
public class Order {
#SerializedName("id")
private int idOrder;
private String status;
private String created;
private String price;
private String volume;
private String pair;
private String type;
private List<Operations> operations;
// All the gets and sets here..
}
Gson doesn't initialize my order object. The order object is always null. I can't find the correct way to implement this mapping.
After a long battle I was able to solve using this solution:
public void deserialize() {
Gson gson = new Gson();
// For isr read InputStreamReader
Map<String, Object> map = gson.fromJson(isr, Map.class);
System.out.println(map.get("success"));
Map<String, Object> map2 = (Map<String, Object>) map.get("return");
// Show the contents of return
System.out.println(map2);
}
After that I used an Entry object to iterate and set the values of Order.
Thanks!

Unexpected Gson object names

I already have some API and cannot change any parameters and object names into.
One of them is it:
{
"version":"1.0",
"error_code":"0",
"error_message":"OK",
"session_id":"2f0513adszdab61a4748553c62019a",
"expire":"2014-12-13 17:38:13",
"currencyData":{
"rate":"1",
"position":"1",
"ch":"dollar"
},
"data":{
"user_id":129733,
"account_type":0
},
"new":{
"messages_count":0,
"purchases_count":0,
"sales_count":0,
"offers_count":0,
"orders_count":0,
"cart_count":9
}
}
In this responce i have objects "currencyData", "data" and "new".
Right now i have troubles with this names after Deserialization, they are null.
My code for getting this recult is:
ApiResponse<UserData> response = new Gson().fromJson(json, UserData.class);
And names for target objects is:
private CurrencyData currencyData;
private UserData data;
private New newz;
Somebody can tell me how i can Deserialize this objects?
try this
private CurrencyData currencyData;
private UserData data;
#SerializedName("new")
private New newz;

How to parse Complex json response in Android

I am trying to parse a JSON response. I am getting JSON response like below:
"libraryLastModified" : "2012-10-10 03:57:26",
"playlists" : { "10063" : { "id" : "10063",
"name" : "Favorites",
"songs" : [ "10006134",
"10006053",
"10006274",
"10006167",
]
},
"10157" : { "id" : "10157",
"name" : "80s",
"songs" : [ "10006694",
"10006695",
"10006697",
"10006699",
"10006698",
]
}
How can I access the id & name values?
I love GSON. In this scenario you'd create two classes.
public class PLayList {
private int id;
private String name;
private List<Integer> songs;
//getters and setters
}
public class Library {
private Date libraryLastModified;
private List<Playlist> playlists;
//getters and setters
}
Then you can write
Gson gson = new Gson();
Library result = gson.fromJson(theInput, Library.class);
Since the playlists is coming to you as key:value you'd need to write a custom deserializer for them. Taje a look at GSON deserializing key-value to custom object for how to do that
In pseudocode. I don't remember exactly the JSON methods
JSONObject mainObj = parseJson
JSONObject playLists = mainObj.getJSONObject("playlists")
JSONObject myList = playList.getJSONObject("10063")
id = myList.getString("id")
To iterate over several lists, you'd better transform playlists to a JSONArray, then you can iterate over it. If you can't do that, check the Android JSON API and check how to get all keys for a JSONObject and then iterate over the keys
for(int i=0;i<playlistKeys.length;i++){
playlistObj = playLists.getJSONObject(playlistsKey[i])
}
use google Gson.
http://code.google.com/p/google-gson/
class Response{
Date libraryLastModified;
Playlist []playlists;
class Playlist{
Long id;
String name;
Long[] songs;
}
}
String _response=... //Your response from web
Response response = new GsonBuilder().setDateFormat("yyyy-MM-dd' 'HH:mm:ss").create().fromJson(_response, Response.class);
String songName = response.playlists[0].name;

Categories

Resources