How to ignore wrap element when parse json to dto - java

I have a json like this
{
"135": {
"id": "135",
"name": "My Awesome Washing Machine!",
"powerswitch": {
"available": "true",
"state": "on",
"reachable": "true",
"locked": "false"
},
"reference": {
"id": "4",
"name": "Lave-linge",
"category_id":"2"
}
},
"491": {
"id": "491",
"name": "My Fridge",
"powerswitch": {
"available": "true",
"state": "on",
"reachable": "false",
"locked": "false"
},
"reference": {
"id": "1",
"name": "Réfrigérateur",
"category_id":"1"
}
}
}
And here is my dto:
public class Device {
private String id;
private String name;
private DevicePowerswitch powerswitch;
private DeviceReference reference;
//getter, setter
}
The question is how can I parse json to a list of device.
Note that there is a non-static id value wrapper in this above json.

You'll need to parse the JSON into a JsonNode, and then iterate over the children. The nodes you pull out as a result can then be mapped using an ObjectMapper to Device instances.
ObjectMapper mapper = new ObjectMapper();
final JsonNode jsonNode = mapper.readTree(JSON);
for (JsonNode node : jsonNode)
{
final Device device = mapper.convertValue(node,
Device.class);
// do something with the device
}

Related

how to mapped java embbeded object with JSON

I build an google Calendar API, and i miss understand a point with my json files.
I succeed to create my java object with my json files but here the issue:
i have two classes :
public class User {
private String email;
private String firstname;
private String lastname;
Entity entity;
``
and my Entity
`` public class Entity {
private String name;
private String entityType;
private Entity rootEntity;``
here my json file :
for user
``[
{
"firstname": "Jean-Marc",
"lastname": "Chevereau",
"email": "xxxxxxx#xxxxx.com",
"entity": {
"name":"BFA",
"entityType":"secteur"
}
},
{
"firstname": "Florent",
"lastname": "Hamlin",
"email": "xxxxxxx#xxxxx.com",
"entity": {
"name":"IT",
"entityType":"secteur"
}
},
{
"firstname": "Benoit",
"lastname": "Micaud",
"email": "xxxxxxx#xxxxx.com",
"entity": {
"name":"EX",
"entityType":"offre",
"rootEntity":{
"name":"BFA"
}
}
}
]``
And a Entity json file
```[
{
"name": "BFA",
"entityType": "secteur",
"rootEntity": "",
},
{
"name": "EX",
"entityType": "Offre",
"rootEntity": "BFA",
}
}
]
But here the trouble. if in my User.json i write theEntity Name, i dont want to write entitytype and rootEntity, because if i write Entity Name is BFA, it will always be the same entitType and the rootEntity.
In others words, my json Entity will be always the same,and if i just put the name we know that refers to an entity object.
For instance, in this user.json file, I will just need to put
[
{
"firstname": "Jean-Marc",
"lastname": "Chevereau",
"email": "xxxxxxx#xxxxx.com",
"entity": {
"name":"BFA",
}
},
{
"firstname": "Florent",
"lastname": "Hamlin",
"email": "xxxxxxx#xxxxx.com",
"entity": {
"name":"IT",
}
},
{
"firstname": "Benoit",
"lastname": "Micaud",
"email": "xxxxxxx#xxxxx.com",
"entity": {
"name":"EX",
}
}
]
In Json-lib you have a JsonConfig to specify the allowed fields:
JsonConfig jsonConfig=new JsonConfig();
jsonConfig.registerPropertyExclusion(Entity.class,"rootEntity");
jsonConfig.registerPropertyExclusion(Entity.class,"entityType");
JSON json = JSONSerializer.toJSON(objectToWrite,jsonConfig);
I suppose com.fasterxml.jackson's #JsonIgnore annotation should help.
public class Entity {
private String name;
#JsonIgnore
private String entityType;
#JsonIgnore
private Entity rootEntity;
}

Java Class to JSON custom Schema by Annotation

I am currently generating my Json Schema like this:
class Item {
public int id;
public string name;
public string description;
}
ObjectMapper mapper = new ObjectMapper();
SchemaFactoryWrapper visitor = new SchemaFactoryWrapper();
mapper.acceptJsonFormatVisitor(Item.class, visitor);
JsonSchema schema = visitor.finalSchema();
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));
Which prints:
{
"type": "object",
"id": "urn:jsonschema:de:foo:bar:User",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"description": { "type": "string" }
}
}
Now I want to append additional information to each type from annotations of the Item class. I want this to provide information for how to display an input for that field.
class User {
public int id;
public string name;
#MyJsonSchemaAnnotation(fieldName = "input", value = "textarea")
public string description;
}
Which will give me:
{
"type": "object",
"id": "urn:jsonschema:de:foo:bar:User",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"description": { "type": "string", "input": "textarea" }
}
}
I think this is similar to #JsonDescription or the JSR 303 Annotations. I'm a bit lost if this is possible at all and if so which way i have to implement it. So if anyone could give me a hint where to look at it would be much appreciated!
The mbknor-jackson-jsonSchema package converts java POJOs to json schema. It has #JsonPropertyDescription annotation which could be used to customize schema.
Note that it only supports till draft 4 of json schema, till now.

Deserialize complex JSON to Java, classes nested multiple levels deep

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

Dynamic Json Parsing Using Gson Android

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.

GSON deserialization of object arrays

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/"
}
]
}

Categories