I need to set json in a format provided below.
"Tyre": {
"title": "Tyre",
"cls": "TyreCondition",
"items": [
{
"firstItem": [
{
"title": "Front right tyre",
"value": "50%",
"subValue": "30,000 km Approx"
}
],
"secItem": [
{
"title": "title",
"value": "Front right tyre tread - 50%"
},
{
"title": "title",
"value": "Front right tyre tread - 50%"
}
]
}
]
}
class that i have created for this is looks like:
private String title;
private String cls;
#SerializedName("firstItem")
private List<UsedCarInspectionInfo> items;
#SerializedName("secItem")
private List<UsedCarTyreImage> imageList;
//getter and setter
when i run this code with this class structure, I am getting the json like-
"Tyre": {
"title": "Tyre",
"cls": "TyreCondition",
"firstItem": [
{
"title": "Front right tyre",
"value": "50%",
"subValue": "30,000 km Approx"
}
],
"secItem": [
{
"title": "title",
"value": "Front right tyre tread - 50%"
},
{
"title": "title",
"value": "Front right tyre tread - 50%"
}
]}
Any idea how i can get the firstItem and secItem array in Items array?
You get no items key in your JSON, because you override the items field in your Java class with #SerializedName.
You need something like this:
String title;
String cls;
List<Item> items;
static class Item {
List<FirstItem> firstItem;
List<SecItem> secItem;
}
static class FirstItem {
String title;
String value;
String subValue;
}
static class SecItem {
String title;
String value;
}
Related
I have a proprietary API that return a complex JSON like:
{
"store": "store_name",
"address": "store_address",
"department": [
{
"name": "d1",
"type": "t1",
"items": [
"i1",
"i2"
]
},
{
"name": "d2",
"type": "t2",
"items": [
"i3"
]
}
],
"itemDescriptions": [
{
"id": "i1",
"description": "desc1"
},
{
"id": "i2",
"description": "desc2",
"innerItems": [
"i2"
]
},
{
"id": "i3",
"description": "desc3"
}
]
}
Is it possible to deserialize this JSON using Jackson into:
#AllArgsConstructor
class Store {
private final String store;
private final String address;
private final List<Department> departments;
/*some logic*/
}
#AllArgsConstructor
class Department {
private final String name;
private final String type;
private final List<Item> items;
/*some logic*/
}
#AllArgsConstructor
class Item {
private final String id;
private final String description;
private final List<Item> innerItems;
/*some logic*/
}
I tried to find answers, but find only this question without solution.
I know that I can do it in my code (deserialize as it is and create objects from result), but its very memory intensive (I have a lot of json and it can be large).
I know that I can write fully custom deserializer, but in this case, I have to describe the deserialization of each field myself - in case of some changes, I will have to change the deserializer, and not just the class(POJO/DTO).
Is there a way to do this with Jackson (or Gson) or with a minimal (preferably relatively generic) amount of my code?
I am trying to make the Json output from Cucumber into a single Java object. This contains objects nested four levels deep, and I am having trouble deserializing it. I am presently using Jackson, but open to suggestions.
Here is my Json code:
{
"line": 1,
"elements": [
{
"line": 3,
"name": "Converteren centimeters naar voeten/inches",
"description": "",
"id": "applicatie-neemt-maten-in-cm-en-converteert-ze-naar-voet/inch,-en-vice-versa;converteren-centimeters-naar-voeten/inches",
"type": "scenario",
"keyword": "Scenario",
"steps": [
{
"result": {
"duration": 476796588,
"status": "passed"
},
"line": 4,
"name": "maak Maten-object aan met invoer in \"centimeters\"",
"match": {
"arguments": [
{
"val": "centimeters",
"offset": 37
}
],
"location": "StepDefinition.maakMatenObjectAanMetInvoerIn(String)"
},
"keyword": "Given "
},
{
"result": {
"duration": 36319,
"status": "passed"
},
"line": 5,
"name": "ik converteer",
"match": {
"location": "StepDefinition.converteerMaten()"
},
"keyword": "When "
},
{
"result": {
"duration": 49138,
"status": "passed"
},
"line": 6,
"name": "uitvoer bevat maat in \"voeten/inches\"",
"match": {
"arguments": [
{
"val": "voeten/inches",
"offset": 23
}
],
"location": "StepDefinition.uitvoerBevatMaatIn(String)"
},
"keyword": "Then "
}
]
},
{
"line": 8,
"name": "Converteren voeten/inches naar centimeters",
"description": "",
"id": "applicatie-neemt-maten-in-cm-en-converteert-ze-naar-voet/inch,-en-vice-versa;converteren-voeten/inches-naar-centimeters",
"type": "scenario",
"keyword": "Scenario",
"steps": [
{
"result": {
"duration": 84175,
"status": "passed"
},
"line": 9,
"name": "maak Maten-object aan met invoer in \"voeten/inches\"",
"match": {
"arguments": [
{
"val": "voeten/inches",
"offset": 37
}
],
"location": "StepDefinition.maakMatenObjectAanMetInvoerIn(String)"
},
"keyword": "Given "
},
{
"result": {
"duration": 23928,
"status": "passed"
},
"line": 10,
"name": "ik converteer",
"match": {
"location": "StepDefinition.converteerMaten()"
},
"keyword": "When "
},
{
"result": {
"duration": 55547,
"status": "passed"
},
"line": 11,
"name": "uitvoer bevat maat in \"centimeters\"",
"match": {
"arguments": [
{
"val": "centimeters",
"offset": 23
}
],
"location": "StepDefinition.uitvoerBevatMaatIn(String)"
},
"keyword": "Then "
}
]
}
],
"name": "Applicatie neemt maten in cm en converteert ze naar voet/inch, en vice versa",
"description": "",
"id": "applicatie-neemt-maten-in-cm-en-converteert-ze-naar-voet/inch,-en-vice-versa",
"keyword": "Feature",
"uri": "sample.feature"
}
I have tried a number of different approaches. First I used nested inner classes, but it appeared you had to make them static, which I feared would not work since I have multiple instances of the same object within one (multiple "element"-objects in the root, for example). Then I tried putting them in separate classes, with Json annotations. Here's where that got me (omitting setters):
public class CucumberUitvoer {
private String name;
private String description;
private String id;
private String keyword;
private String uri;
private int line;
#JsonProperty("elements")
private List<FeatureObject> elements;
public CucumberUitvoer(){}
}
public class FeatureObject {
private String name;
private String description;
private String id;
private String type;
private String keyword;
private int line;
#JsonProperty("steps")
private List<StepObject> steps;
public FeatureObject() {
}
}
public class StepObject {
#JsonProperty("result")
private ResultObject result;
private String name;
private String given;
private String location;
private String keyword;
private int line;
#JsonProperty("match")
private MatchObject match;
public StepObject(){}
}
public class ResultObject {
private int duration;
private String status;
public ResultObject(){}
}
public class MatchObject {
#JsonProperty("arguments")
private List<ArgumentObject> arguments;
private String location;
public MatchObject(){}
}
public class ArgumentObject {
private String val;
private String offset;
public ArgumentObject(){}
}
For clarification, here's a class diagram of how the nesting works.
This solution gives me the following error:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of nl.icaprojecten.TestIntegratieQuintor.JSONInterpreter.CucumberUitvoer out of START_ARRAY token
Here is the code doing the actual mapping:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
CucumberUitvoer obj1 = null;
try {
obj1 = mapper.readValue(json, CucumberUitvoer.class);
} catch (IOException e) {
e.printStackTrace();
}
Is there a quick fix to this approach to make it work, or should I try something entirely different?
Ok I spent some time debugging and trying to figure out what was the problem, and finally was something pretty obvious.
implements Serializable
Thats the line I added to MatchObject and worked.
When we try to deserialize some object first we have to make those classes implements the interface Serializable
I just tried your sample code and oddly, it works.
Can you please double check your imports, if the JSON is coming in as provided and the getters, setters, constructors are actually there?
You can get the idea from this code to deserialize,
public class testCustomDeSerializer extends JsonDeserializer<test> {
public testCustomDeSerializer() {
this(null);
}
public TestCustomDeSerializer(Class t) {
// super(t);
}
#Override
public Test deserialize(JsonParser p, DeserializationContext ctx) throws IOException, JsonProcessingException {
ObjectCodec objectCodec = p.getCodec();
JsonNode node = objectCodec.readTree(p);
ObjectMapper objectMapper = new ObjectMapper();
Test test= new Test();
test.setId(node.get("line").asText());
List<elements> elementList = new ArrayList<>();
JsonNode elementsNode = node.get("elements");
Iterator<JsonNode> slaidsIterator = elementsNode.elements();
while (slaidsIterator.hasNext()) {
Steps steps= new Steps();
JsonNode slaidNode = slaidsIterator.next();
JsonNode stepNode= (JsonNode) slaidNode.get("Steps");
BoundingPoly in = objectMapper.readValue(stepNode.toString(), Steps.class);
elementsNode.setSteps(in);
/// continue
return
}
Hope it helps
I have a json as mentioned below.
{
"product": [
{
"classification": "abc",
"ABC": [
{
"classification": "abc",
"name": "abc new product one",
"price": "10775.0000",
},
{
"classification": "abc",
"name": "abc new product two",
"price": "12725.0000",
}
]
},
{
"classification": "def",
"DEF": [
{
"classification": "def",
"name": "def product one",
"price": "728.0000",
},
{
"classification": "def",
"name": "def product two",
"price": "1263.0000",
},
]
}
],
"status": "OK",
"message": "success"
}
In the above json, the key in capital letter is dynamic
(Ex: ABC, DEF)
. I've created pojo class as below:
public class ProductResponse{
private String status;
private String message;
private List<Products>;
Getters And Setters
}
public class Products{
private String classification;
}
I'm struggling to write the next part in Products pojo class, As the keys which are in capitals
(Ex: ABC, DEF)
are dynamic. I am using volley library for getting the data and for parsing I'm using gson library. Please help me out.
You can't have a dynamic name. the reason being is the name in your json needs to be linked to an attribute in your object.
I recommend you to add a "classification" attribute in your json and your model as following :
{
"type": "def",
" results": [
{
"name": "def product one",
"price": "728.0000",
},
{
"name": "def product two",
"price": "1263.0000",
},
]
}
public final class ProductResponse{
private String status;
private String message;
private List<Products> product = new Arraylist<>();
// Getters And Setters
}
public final class Products{
private String type; // type of product // ABC or DEF
private List<Result> results = new Arraylist<>();
// Getters And Setters
}
public final class Result{
private String name;
private String price;
// Getters And Setters
}
Your products class has now a list of results associated to a classification !
Hope it helps !
Your problem is the dynamic key, which I found is not dynamic. As I can see, For each element in the product array, the classification key's value is the next key. Only difference is that they are in capital letters.
{
"classification": "def",
"DEF": [
{
"classification": "def",
"name": "def product one",
"price": "728.0000",
},
{
"classification": "def",
"name": "def product two",
"price": "1263.0000",
},
]
}
As in, here "classification": "def" and the next key is DEF. What I would do here is get the value of classification key, capitalize all the letters in the string and then use it as the key.
I have json response in the form
{
"total": 782,
"category": {
"id": 1120,
"name": "Computers & Programming"
},
"experts": [
{
"id": 385816,
"name": "Master Z",
"title": "Mr",
"description": " Expert in C++",
"profile": "http://...com/experts.svc/1.0/385816/..../json?.."
}
}
]
}
I am able to parse everything else in the experts[] array except "profile" whose value "http://...com/experts.svc/1.0/385816/..../json?.." has the following json response
{
"id": 385816,
"name": "Master Z",
"title": "",
"reviewsCount": 15359,
"averageRating": 4.87,
"status": 4,
"fee": 19.99,
"languages": "English",
"category": {
"id": 1120,
"name": "Computers & Programming"
}
}
The models used are as follows
1. main pojo:
public class ExpertObj
{
private String total;
private Category category;
private Experts[] experts;
}
Category pojo:
public class Category
{
private String id;
private String name;
}
3.Experts array pojo:
public class Experts
{
private String id;
private String name;
private String title;
private String description;
private String profile;
}
Am using Retrift 2.
private RestManager mManager;
List<Expert> mExperts = new ArrayList<>();
....
Call<ExpertsObj> call = mManager.getExpertsService().listAllExperts();
call.enqueue(new Callback<ExpertsObj>() {
#Override
public void onResponse(Call<ExpertsObj> call, Response<ExpertsObj> response) {
if (response.isSuccess()) {
ExpertsObj expertsObj = response.body();
mExperts = expertsObj.getExperts();
....}
At a loss how to parse the profile-url name-value pair and display the results in a detail layout in android.
Any help is appreciated.
New in android. Please excuse if anything is not explained properly.
I have a class with the following attributes
public class JenkinsServer
{
private String url;
private String mode;
private String nodeName;
private String nodeDescription;
private String description;
private boolean useSecurity;
private boolean quietingDown;
private JenkinsServerView primaryView;
private List< JenkinsJob > jobs;
private List< JenkinsServerView > views;
}
Now I want GSON to deserialize/map a json document to it. It works well, except for my lists - they are empty. The json document looks as follows (snippet):
"jobs": [
{
"name": "AnotherJob",
"url": "https://build.example.com/jenkins/job/AnotherJob/",
"color": "disabled"
},
{
"name": "AnotherJob2",
"url": "https://build.example.com/jenkins/job/Build%20CI%20Build/",
"color": "blue"
},
"views": [
{
"name": "-All Views",
"url": "https://build.example.com/jenkins/view/-All%Views/"
},
{
"name": "Alle",
"url": "https://build.example.com/jenkins/"
},
The mapping works, even for the single instance of
JenkinsServerView primaryView
but not for the Lists. I'm starting the mapping this way:
Gson gson = gsonBuilder.create();
JenkinsServer server = gson.fromJson( reader, JenkinsServer.class );
looks your json data that you are trying to parse is invalid.
In your json jobs and views are arrays and both of them doesn't have the closing brace at the end.
The valid json will be as follows: (Observe the closing braces at the end of the array)
{
"jobs": [
{
"name": "AnotherJob",
"url": "https://build.example.com/jenkins/job/AnotherJob/",
"color": "disabled"
},
{
"name": "AnotherJob2",
"url": "https://build.example.com/jenkins/job/Build%20CI%20Build/",
"color": "blue"
}
],
"views": [
{
"name": "-All Views",
"url": "https://build.example.com/jenkins/view/-All%Views/"
},
{
"name": "Alle",
"url": "https://build.example.com/jenkins/"
}
]
}