How to map json to java object using json property - java

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);
}

Related

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.

Dynamic serialization/deserialization

I use Spring MVC and Jackson to drive the API of a application that I work in. I am faced with the following situation, we need serialize the Person class below in two different ways...
#Entity
Order{
String id;
String name;
String address;
List<Items> items;
}
#Entity
Item{
String id;
String description:
}
The two situations reposes on the serialization or not of the content of the "items" field in accord with the service that was called.
For example, the service http://localhost/order, results without the "items" field.
{
"id": "1",
"name" : "Bill",
"address" : "any address",
}
In the other hands, the second way is http://localhost/order/[id_order]/item/[ids_items], results with the field "items" that was give on the parameter.
{
"id": "1",
"name" : "Bil",
"address" : "any",
"items" : [{
"id" : "33",
"description" : "Item 33"
}]
}
#JsonView
You can use #JsonView to filter fields depending on the context of serialization. It is supported by Spring MVC.
First define your views:
public class View {
interface Default { }
interface Detailed extends Default { }
}
Then annotate your fields using the desired view:
#Entity
public class Order {
#JsonView(View.Default.class)
private String id;
#JsonView(View.Default.class)
private String name;
#JsonView(View.Default.class)
private String address;
#JsonView(View.Detailed.class)
private List<Items> items;
// Getters and setters
}
Finally annotate your controller methods to use a view when serializing the response:
#JsonView(View.Default.class)
#RequestMapping(value = "/order", method = RequestMethod.GET)
public ResponseEntity<Order> getOrder() {
...
}
#JsonView(View.Detailed.class)
#RequestMapping(value = "/order-with-items", method = RequestMethod.GET)
public ResponseEntity<SampleResults> getOrderWithItems() {
...
}
In order to make it work, you may need to disable the default view inclusion in your ObjectMapper:
mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
With jackson you can modify the result json string on the fly. For example:
// create a new order
Order order = new Order("id", "name", "addr");
ObjectMapper mapper = new ObjectMapper();
// create a json string with the order
JsonNode node = mapper.valueToTree(order);
//the content of the node at this moment is:
//{"id":"id","name":"name","address":"addr"}
// create an ArrayList with the Items
ArrayList<Item> items = new ArrayList<Item>();
items.add(new Item("id1", "desc1"));
items.add(new Item("id2", "desc2"));
// transform the ArrayList to a json string and add it
// the the previous node with the Order
((ObjectNode)node).put("items", mapper.valueToTree(items));
String jsonString = node.toString();
System.out.println(jsonString);
The final output is:
{"id":"id","name":"name","address":"addr","items":[{"id":"id1","description":"desc1"},{"id":"id2","description":"desc2"}]}
For more information visit the official documentation page: https://github.com/FasterXML/jackson-databind/

Form pojo to parse JSON

My json looks like this :
{
"bid": "181.57",
"ask": "181.58",
"volume": {
"item1": "543.21",
"item2": "123.45",
"timestamp": 1487903100000
},
"last": "181.58"
}
I'm trying to use spring restTemplate to read it into a pojo. My current pojo is this :-
import com.fasterxml.jackson.annotation.JsonProperty;
public class DataModel {
private String last;
private Volume volume;
private String ask;
private String bid;
// Getter and setters
}
class Volume
{
private String timestamp;
#JsonProperty
private String item1;
#JsonProperty
private String item2;
// Gettersand setters
}
The problem is that "item1" and "item2" int the json can change to "item5" and "item6" depending on which entity I am querying for. I get null values if my variables are named item1 and item2. How can I keep generic names for the variables item1 and item2 and still be able to read the values correctly in the generic variables? Is there any annotation that will help here?
I believe this is what you are looking for from a Baeldung tutorial:
3.3. #JsonAnySetter
#JsonAnySetter allows you the flexibility of using a Map as standard properties. On de-serialization, the properties from JSON will simply be added to the map.
Let’s see how this works – we’ll use #JsonAnySetter to deserialize the entity ExtendableBean:
public class ExtendableBean {
public String name;
private Map<String, String> properties;
#JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
}
This is the JSON we need to deserialize:
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
And here’s how this all ties in together:
#Test
public void whenDeserializingUsingJsonAnySetter_thenCorrect()
throws IOException {
String json
= "{\"name\":\"My bean\",\"attr2\":\"val2\",\"attr1\":\"val1\"}";
ExtendableBean bean = new ObjectMapper()
.readerFor(ExtendableBean.class)
.readValue(json);
assertEquals("My bean", bean.name);
assertEquals("val2", bean.getProperties().get("attr2"));
}
In your case, you would simply query the map for the String values you expect for whichever query you are making.

How to get plain JSON data in jersey REST implementation?

If we have a POJO class, then we can map it with some incoming JSON. I am struggling to find out a way by which I can just have all plain json value inside.
For ex.
{
"macro_tasks": [
{
"id": "cc5cee68-c1e5-4396-987b-c68559399186",
"label": "consi-1",
"name": "Consi 1",
"project_id": "82d1e463-1bb1-42d3-9adc-9e0d5848d139",
"creator_id": null,
"created_at": null,
"updated_at": null,
"meta_data": {
"key1": "value1",
"key2": 321
}
}
]
}
Here meta_data is of JSON type which can keep changing its values inside. So I cannot map it with some POJO class.
public class MacroTask {
private UUID id;
private String label;
private String name;
private UUID projectId;
private UUID creatorId;
private String createdAt;
private String updatedAt;
private <some data type> meta_data;
//getter and setter
Is there any way to get plain JSON data and use it in code and dump into DB [we are using PostgreSQL, which supports jsonb type.]
I solved it by using Generic JSON type, Jackson's JsonNode. It has some drawbacks as I heard, but I am giving it a try. So far, it's working as per expectations. I will update if I face any challenge or I find any better solution.
You can use map; like
private Map<String, Object> meta_data;
I got following error
Can not deserialize instance of java.lang.String out of START_OBJECT
I was using this code for json string to HasMap conversion.
Map map = mapper.readValue(jsonString, new TypeReference<HashMap<String,String>>(){});
I replaced it with.
Map map = mapper.readValue(jsonString, new TypeReference<HashMap<String,Object>>(){});

convert json into Value pairs

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);

Categories

Resources