convert json into Value pairs - java

I have Json(entire format of json can vary everytime) string as follows,
{"domain": {
"id": "file",
"value": "Content",
"popup": {
"menuitem1": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}
which i have converted to a map,which has the key and value as follows,
Map<String, Object> jsonMap = new HashMap<String, Object>();
ObjectMapper mapper = new ObjectMapper();
jsonMap = mapper.readValue(jsonString,new TypeReference<HashMap<String,Object>>(){});
KEY :domain
VALUE :{id=file, popup={menuitem=[{value=New, onclick=CreateNewDoc()}, {value=Open, onclick=OpenDoc()}, {value=Close, onclick=CloseDoc()}],}, value=Content}
How to access each value by passing its name to the map,like
map.get(id) = file
map.get(popup) = {menuitem=[{value=New, onclick=CreateNewDoc()}, {value=Open, onclick=OpenDoc()}, {value=Close, onclick=CloseDoc()}]}
map.get(value) = Content

If you want to get from the map the inner field you need to use a very uncomfortable syntax like this:
((Map<String, Object>)jsonMap.get("domain")).get("id") // returns "file"
I think that you can read your json in a convenient class that you can create manually.
The class will have all the fields contained in the json and you will have access to them using get methods.
class DomainClass {
public InnerDomain domain;
}
class MenuItem {
public String value;
public String onclick;
}
class PopupClass {
public List<MenuItem> menuitem1;
}
class InnerDomain {
public String id;
public String value;
public PopupClass popup;
}
The class DomainClass is the main class that you need to use to deserialize your json. Using jackson is pretty easy and it looks like the method that you've used in your case:
ObjectMapper mapper = new ObjectMapper();
DomainClass domainObj = mapper.readValue(jsonString, DomainClass.class);
// print the id field
System.out.println(domainObj.domain.id);

Related

How to ignore JSON properties similar to #JsonIgnore in Deserialization

I have a JSON object similar below:
[
{
"objA": {
"propA": "AAAA",
"propB": "BBBB",
"objB": {
"objC": {
"propC": "CCCC",
"propD": "DDDD"
}
},
"objD": [
"asa"
],
"propE": "AW",
"propF": "533",
"propG": "ABW",
"propH": "ARU",
"objE": {
"objF": {
"propI": "SASDS",
"propJ": "54DEFF"
}
}
}
}
]
When I deserialize this JSON into a List, I would like to do for part of this object, for example: I would like to ignore objB, objC, objD, objE and objF.
To do that I has been used the #JsonIgnore annotation. So I did something like that:
public class MyClass {
// objects and properties not ignorabled
private ClassA objA;
private String propE;
private String propF;
private String propG;;
private String propH;
// objects ignorabled in deserialization
#JsonProperty("objB")
#JsonIgnore
private Object objB;
#JsonProperty("objD")
#JsonIgnore
private Object objD;
#JsonProperty("objE")
#JsonIgnore
private Object objE;
/** gets and setters here **/
Follow below the piece of code that deserialize my JSON
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(url, new TypeReference<List<MyClass>>(){});
This code is working. this code is ignoring the objects from JSON, but I believe there are some another way to do that instead of use #JsonIgnore to each object or property in my entity.
Do you know how can I do that better?
Do you want to avoid using # notations ?
If not, have you tried using a filter like #JsonFilter("myFilter") in Jackson ? As described here: https://www.baeldung.com/jackson-ignore-properties-on-serialization
See also https://www.tutorialspoint.com/jackson_annotations/jackson_annotations_jsonfilter.htm
So you would have to write:
#JsonFilter("myFilter")
public class MyClass { ... }
in your class. Then do something like:
SimpleBeanPropertyFilter objBFilter = SimpleBeanPropertyFilter
.serializeAllExcept("objB");
SimpleBeanPropertyFilter objDFilter = SimpleBeanPropertyFilter
.serializeAllExcept("objD");
SimpleBeanPropertyFilter objEFilter = SimpleBeanPropertyFilter
.serializeAllExcept("objE");
FilterProvider filters = new SimpleFilterProvider()
.addFilter("objBFilter", theFilter)
.addFilter("objDFilter", theFilter)
.addFilter("objEFilter", theFilter);

Jackson: Deserialize JSON array from JSON object into Java List

I have been stumbled by this for a while. I have a Spring application and would like to parse the following JSON:
{
"metadata": {...}
"response": {
"objects": [
{
"name": "someName",
"properties": [<array_of_properties>]
},
...
]
}
}
into a list of the following Java objects:
public class MyClass {
String name;
List<CustomProperties> customProperties;
}
Meaning, I want to extract only the objects array and parse only that. I have tried using a custom deserializer and that works, but I had to do:
#JsonDeserialize(using=MyDeserializer.class)
public class MyClassList extends ArrayList<MyClass>{}
and then:
ObjectMapper objectMapper = new ObjectMapper();
List<MyClass> list = objectMapper.readValue(json, MyClassList.class)
Is there anyway to avoid extending ArrayList, since currently I am doing that in order to be able to access the .class property.
you can define your json structure with a couple of classes
public class MyJson {
private MyResponse response;
...
}
public class MyResponse {
private List<MyClass> objects;
...
}
public class MyClass {
String name;
List<CustomProperty> customProperties;
...
}
than you can use Jackson to parse the json string to MyJson class, no special #JsonDeserialize is needed
ObjectMapper objectMapper = new ObjectMapper();
MyJson myJson = objectMapper.readValue(json, MyJson.class);
List<MyClass> list = myJson.getResponse().getObjects();
Keep in mind, this code is only a draft, all classes should have setters (and getters) and some null checks are required
You can do something like this. I feel this would be cleaner
#JsonIgnoreProperties(ignoreUnknown = true)
class Wrapper{
private Response response;
//setters, getters
}
#JsonIgnoreProperties(ignoreUnknown = true)
class Response{
private List<MyClass> objects;
//setters, getters
}
#JsonIgnoreProperties(ignoreUnknown = true)
public class MyClass {
String name;
List<CustomProperties> customProperties;
//setters, getters
}
ObjectMapper objectMapper = new ObjectMapper();
Wrapper wrapper = objectMapper.readValue(json, Wrapper.class)
You can extrat objects and consequently CustomProperties by traversing the list. You can declare only fields which you are interested in and ignore others by #JsonIgnoreProperties(ignoreUnknown = true)(for example i have not included metadata)

Is Jackson Serialization of this string possible without custom serializer?

I want to serialize a JSON-String I receive as a POJO, for further usage in my code, but I am struggling to get it working without writing a custom serializer.
I would prefer as solution without writing a custom serializer, but if that is the only possible way I will write one.
Additionally I believe the data I receive is a weird JSON since the list I request is not sent as list using [] but rather as a object using {}.
I receive the following list/object (shortened):
{
"results": {
"ALL": {
"currencyName": "Albanian Lek",
"currencySymbol": "Lek",
"id": "ALL"
},
"XCD": {
"currencyName": "East Caribbean Dollar",
"currencySymbol": "$",
"id": "XCD"
},
"EUR": {
"currencyName": "Euro",
"currencySymbol": "â?¬",
"id": "EUR"
},
"BBD": {
"currencyName": "Barbadian Dollar",
"currencySymbol": "$",
"id": "BBD"
},
"BTN": {
"currencyName": "Bhutanese Ngultrum",
"id": "BTN"
},
"BND": {
"currencyName": "Brunei Dollar",
"currencySymbol": "$",
"id": "BND"
}
}
}
I created my first POJO for the inner object like this:
public class CurrencyDTO implements Serializable {
private String currencyName;
private String currencySymbol;
private String currencyId;
#JsonCreator
public CurrencyDTO( #JsonProperty( "currencyName" ) String currencyName, #JsonProperty( "currencySymbol" ) String currencySymbol,
#JsonProperty( "id" ) String currencyId )
{
this.currencyId = currencyId;
this.currencyName = currencyName;
this.currencySymbol = currencySymbol;
}
}
which itself is fine. Now I wrote another POJO as a wrapper for the data a layer above which looks like this:
public class CurrencyListDTO implements Serializable {
private List<Map<String, CurrencyDTO>> results;
public CurrencyListDTO()
{
}
}
Adding the annotations #JsonAnySetter or using the #JsonCreator didn't help either, so I removed them again and now I am wondering which little trick could enable the correct serialization of the json.
My Exception is the following:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token
at [Source: (String)"{"results":{"ALL":{"currencyName":"Albanian Lek","currencySymbol":"Lek","id":"ALL"},"XCD":{"currencyName":"East Caribbean Dollar","currencySymbol":"$","id":"XCD"},"EUR":{"currencyName":"Euro","currencySymbol":"â?¬","id":"EUR"},"BBD":{"currencyName":"Barbadian Dollar","currencySymbol":"$","id":"BBD"},"BTN":{"currencyName":"Bhutanese Ngultrum","id":"BTN"},"BND":{"currencyName":"Brunei Dollar","currencySymbol":"$","id":"BND"},"XAF":{"currencyName":"Central African CFA Franc","id":"XAF"},"CUP":{"cur"[truncated 10515 chars]; line: 1, column: 12] (through reference chain: com.nico.Banking.api.data.dto.CurrencyListDTO["results"])
You should change your CurrencyListDTO to:
public class CurrencyListDTO {
private Map<String, CurrencyDTO> results;
// getters and setters
}
Because the results field in the response object is another object with the currencyId as key and no array.
You then can create your list of currencies like this:
ObjectMapper mapper = new ObjectMapper();
CurrencyListDTO result = mapper.readValue(json, CurrencyListDTO.class);
List<CurrencyDTO> currencies = new ArrayList<>(result.getResults().values());
Your CurrencyListDTO should look like below. results property is a JSON Object which should be mapped directly to Map. You can convert it to Collection using keySet or values methods.
class CurrencyListDTO implements Serializable {
private Map<String, CurrencyDTO> results;
public Map<String, CurrencyDTO> getResults() {
return results;
}
public void setResults(Map<String, CurrencyDTO> results) {
this.results = results;
}
#Override
public String toString() {
return "CurrencyListDTO{" +
"results=" + results +
'}';
}
}

Parsing json string to java with complex datastructure(jackson)

I am trying to convert the below json string to java object, but i am getting empty object.
Under prop2 object, there can be any number of key value pairs(where key is a string and value is a array )
{
"Level1": {
"prop1": "",
"prop2": {
"one": [{
"ip": "1.2.3.4",
"port": "100"
}],
"ten": [{
"ip": "10.20.20.10",
"port": "200"
}]
}
}
}
I have this class structure, however i am getting ipAndPorts map as empty.
#JsonIgnoreProperties(ignoreUnknown = true)
static class Root {
#JsonProperty("Level1")
private Level1 level1;
}
#JsonIgnoreProperties(ignoreUnknown = true)
static class Level1 {
#JsonProperty("prop2")
private Prop2 prop2;
}
#JsonIgnoreProperties(ignoreUnknown = true)
static class Prop2 {
private Map<String, List<IpAndPort>> ipAndPorts = Collections.emptyMap();
}
#JsonIgnoreProperties(ignoreUnknown = true)
static class IpAndPort {
#JsonProperty("port")
private String port;
}
How should my java class look like, to represent "prop2" correctly?
For the record: The problem was solved by using
#JsonIgnoreProperties(ignoreUnknown = true)
static class Level1 {
#JsonProperty("prop2")
private Map<String, List<IpAndPort>> ipAndPorts = Collections.emptyMap();
}
directly without the Prop2 class. Otherwise Jackson would expect a JSON property called ipAndPorts under prop2 JSON object.
I would sudgest that you would first create your Java class the way want it to look like, then use Jackson to serialize it to JSON. you will see what is the structure of resultant JSON and see if and how you will need to modify your class.

How to map json to java object using json property

I can not map this json in java object. issue is i can not map the values v0.1.0 to my java object can any one help me how i can map this json to java object.I am not declare varaible name with v0.1.0 so i use json property annotation . but this is not work for me.
How to make java object from this json :
{
"availableVariants": {
"v0.1.0": {
"resourceName": "raja",
"get": "www.google.com",
"deltaGet": "",
"post": null,
"put": null,
"delete": null
},
"v1.1.0": {
"resourceName": "raja",
"get": "www.google.com",
"deltaGet": "",
"post": null,
"put": null,
"delete": null
}
}
}
I am not able to make java object for this json .
Does the problem get simpler if you think of "v0.1.0" and "v1.1.0" as keys in a map instead of properties of an object? Try something like this:
public class Resource {
private String resourceName;
private String get;
private String deltaGet;
private String post;
private String put;
private String delete;
// public getters and setters
}
public class VariantInfo {
// resources indexed by version
private Map<String, Resource> availableVariants;
// public getter and setter
}
public VariantInfo parseVariants(String json) {
ObjectMapper objectMapper = (wherever your Jackson object mapper comes from);
return objectMapper.readValue(json, VariantInfo.class);
}

Categories

Resources