Modify Jackson response - java

I have two classes:
class A {
int id;
String name;
}
class B {
String property1;
String property2;
String property3;
}
when A extends B
Response:
{
"property1": "value1",
"property2": "value2",
"property3": "value3"
"id":1,
"name": 'my name"
}
Instead, I want to display them as below:
{
"id":1,
"name": 'my name',
"property1": "value1",
"property2": "value2",
"property3": "value3"
}

The order of the fields within JSON object shouldn't matter. As per the spec:
An object is an unordered set of name/value pairs
So what you're asking doesn't really make sense.

You should be able to use JsonPropertyOrder annotation for this.
#JsonPropertyOrder({"id", "name", "property1", "property2", "property3"})
class B {
...

Related

How to make sure order of map elements inside a #RequestBody of POST REST API is maintained?

The RequestBody entity Person in a POST request has a map as following
class Person {
String name;
int age;
Map<String, String> otherProperties;
}
The above entity is mapped via RequestBody as following:
public void processInput(#RequestBody Person person) {
}
Though the invoker of this API sends following JSON in the input:
{
"name": "nameOfPerson",
"age": 10,
"otherProperties": {
"key1": "val1",
"key2": "val2",
"key3": "val3"
}
}
the spring controller processes it as :
{
"name": "nameOfPerson",
"age": 10,
"otherProperties": {
"key2": "val2",
"key3": "val3",
"key1": "val1",
}
}
The order of the map inside the entity is not maintained.
How to make sure the Spring controller reads and processes the map in the right order as was being sent by the invoker?
LinkedHashMap implementation or other implementation of Map does not guarantee that the input order be maintained.
You could create an object that contains your key and value, and then use a list instead of a map when passing the json object.
class Person {
String name;
int age;
List<PersonProperty> otherProperties;
}
class PersonProperty {
String name;
String value;
}
{
"name": "nameOfPerson",
"age": 10,
"otherProperties": [
{"name":"key1", "value":"val1"},
{"name":"key2", "value":"val2"},
{"name":"key3", "value":"val3"}
]
}

How to manipulate nested Json Data to de-Nest in java

I have been looking solution for this problem but could not find one so asking this question.
I have some data which looks like this
{
"data": [
{
"id": "5ab892c71810e201e81b9d39",
"isSignedUpUsingFb": false,
"personalInformation": {
"firstName": "jio",
"lastName": "g",
"mobileNumber": "1234567890",
},
"accountBalance": 0,
}
]
},
I want to write a java code to change the data structure to this
{
"data": [
{
"id": "5ab892c71810e201e81b9d39",
"isSignedUpUsingFb": false,
"personalInformation_firstName":"jio",
"personalInformation_lastNAme":"g",
"personalInformation_mobileNumber":"1234567890",
"accountBalance": 0,
}
]
},
I am getting data from db as:
#Override
public List<User> getAllUsers() {
logger.debug("entering all users method");
List<User> allUsers=mongoOperations.findAll(User.class);
for (User user : allUsers) {
PersonalInformation info=user.getPersonalInformation());
//manipulation code here
user.setPersonalInformation(info);
}
return allUsers;
}
So I want to write a logic so that i can convert the data in desired format and send it a return type. I know how to do same thing using J query but I want to do it in backend so any code for the above or any link will help.
I have fond one solution which is very simple.So, basically when we create object for nested data we create it like this in JAVA.
public MyClass{
public String name;
public String contact;
public PersonalInformation personalinformation;
//setters and getter here
}
this will give me data as
"MyClass":{
"name": "abc",
"contact": "12345",
"personalInformation":{
"address": "asdasdasdad",
"city":"asdadad",
"pin": "asdfg",
}
}
so to remove this nested data we need to use #JsonUnwrapped which removes all the nested object and add it to our main object.
public MyClass{
public String name;
public String contact;
#JsonUnwrapped
public PersonalInformation personalinformation;
//setters and getter here
}
which will change the data structure as:
"MyClass":{
"name": "abc",
"contact": "12345",
"address": "asdasdasdad",
"city":"asdadad",
"pin": "asdfg",
}
for more reference you can check this link http://fasterxml.github.io/jackson-annotations/javadoc/2.0.0/com/fasterxml/jackson/annotation/JsonUnwrapped.html
Hope this helps.
There are multiple possible solutions. As Prabhav has mentioned the most intuitive one would be to create a new class and from there a object which can be transformed with a library to a JSON.
Variant one:
The new class would look like your data structure you want and access would be:
PersonalInformationJson pf = new PersonalInformationJson();
pf.setFirstName = info.getPersonalInformation_firstName
//... setting the rest of the object
//using jackson
ObjectMapper mapper = new ObjectMapper();
try {
// convert user object to json string and return it
String jsonString = mapper.writeValueAsString(u);
}
The other easier version to create a string, either per hand or use a lib:
// using org.json.JSONObject
String jsonString = new JSONObject().put("personalInformation_firstName", info.value())
.put("personalInformation_lastNAme", info.value());

How construct list of objects from json string coming from api response?

Similar question might be asked before on here, but I had no luck and I was wondering how to extract specific objects like user in from below json string and then construct an ArrayList. However, there is one twist, one of the property directly under Users is a random number, which can be anything!!!
Here is how my json string looks like:
<code>{
"_links": {
},
"count": {
},
"users": {
"123321": { //*Is a random number which can be any number
"_links": {
},
"user": {
"id": "123321",
"name": "...",
"age": "...",
"address": ""
..
}
},
"456654": {
"_links": {
},
"user": {
"id": "456654",
"name": "...",
"age": "...",
"address": ""
...
}
}
...
},
"page": {
}
}
</code>
The java object I would like to transform it to is:
#JsonIgnoreProperties(ignoreUnknown = true) // Ignore any properties not bound here
public class User {
private String id;
private String name;
//setter:getter
}
Note: The transformation should only consider those two fields (id,name), and ignore the rest of the fields from the json response user:{} object.
Ideally, I would like to end up with a list like this:
List<User> users = resulted json transformation should return a list of users!!
Any idea how can I do this please ideally with Jackson JSON Parser/ or maybe GSON?
Since the user keys are random, you obviously can't map them to a named Java field. Instead, you can parse the top-level object as a map and the manually pull out the user objects.
public class UserWrapper {
private User user;
public User getUser() { return user; }
}
public class Root {
private Map<String, UserWrapper> users;
public List<User> getUsers() {
List<User> usersList = new ArrayList();
for (String key : map.keySet()) {
UserWrapper wrapper = map.get(key);
usersList.add(wrapper.getUser());
}
return userList;
}
}
Root root = parseJson();
List<User> users = root.getUsers()
Hope that helps!
jolt transformer is your friend. Use shift with wildcard * to capture arbitrary node value and then standard mappers (Jackson /gson) .

How To Use Jackson's #JsonIdentityInfo for Deserialization of directed Graphs?

I want to use Jackson 2.3.3 for Deserialization/Serialization of directed graphs. The structure I came up with is roughly the following:
public Class Graph {
private final Set<Node> nodes;
public Graph(Set<Node> nodes) { ... }
public Set<Node> getNodes() { ... }
}
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "name")
public Class Node {
private final String name;
private final Set<Edge> edges;
public Node(String name, Set<Edge> edges) { ... }
public String getName() { ... }
public Set<Edge> getEdges() { ... }
}
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "name")
public Class Edge {
private final String name;
private final Node successor;
public Edge(String name, Node successor) { ... }
public String getName() { ... }
public Node getSuccessor() { ... }
}
And I expect to have this JSON-Structure:
{
"graph": [{
"name": "A",
"edges": [{
"name": "0",
"successor": "B"
}, {
"name": "1",
"successor": "A"
}]
}, {
"name": "B",
"edges": [{
"name": "0",
"successor": "A"
}, {
"name": "1",
"successor": "B"
}]
}]
}
But I get the following error while deserialization (even with annotation #JsonProperty("name") at the Getters):
com.fasterxml.jackson.databind.JsonMappingException: Invalid Object Id definition for some.package.graph.Node: can not find property with name 'name'
I have found some solutions for Jackson 1.6 with Back-Reference Annotations, but I'd like to use the new Jackson 2.x Annotation, as it was advertised so much in the API Update from 1.9 to 2.0 of Jackson.
What point am I missing here? Thanks for constructive answers in advance.
EDIT
(Removed my answer from here to the Answer section)
I got kind of blind of staring too long at it. Here's what's gone wrong:
The Serialization actually worked as intended. What didn't work was the Deserialization, because Jackson wasn't able to instantiate my Node-Object. I simply forgot to annotate the parameters of the constructor methods correctly.
I was now facing another problem. The generated JSON now looked like this:
"graph": {
"nodes": [{
"name": "B",
"edges": [{
"label": "1",
"successor": "B"
}, {
"label": "0",
"successor": {
"name": "A",
"edges": [{
"label": "1",
"successor": "A"
}, {
"label": "0",
"successor": "B"
}]
}
}]
}, "A"]
}
So far so good. But during mapping, Jackson confronts me with this Error:
java.lang.IllegalStateException: Could not resolve Object Id [B] (for [simple
type, class some.package.graph.Node]) -- unresolved forward-reference?
I even changed the Label of the edges because I thought the same property name might confuse Jackson here, but that didn't help either...
My guess here is that Jackson can't reference the Node B, because it is still being constructed (you could say it is actually some kind of root in this example). The only way to fix this seems to construct all the Nodes without the edges and inject them in a second step.

Can I push jackson-mapped #JsonProperties to the "top level"?

Given a Java class like the following:
class MyClass {
String value;
Map<String,Object> map;
#JsonProperty("value")
public String getValue() {
return value;
}
#JsonProperty("map")
public Map<String,Object> getMap {
return map;
}
}
Jackson will convert to JSON like so:
{
"value": "abc",
"map": {
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
}
What I would like instead is to "flatten" the map attribute somehow so its contents appears at the "top-level" of the JSON structure like this:
{
"value": "abc",
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
Is that possible declaratively through any combinations of Jackson annotations?
(This is a simplification of my actual problem, so I am not looking for an answer like "write your own custom MyClass serializer." In reality, this class must work with custom ObjectMappers in a scenario out of my direct control.)
you can try #JsonUnwrapped
As per link, this is supposed to remove a layer of wrapping.
(Jackson 1.9+) #JsonUnwrapped (property; i.e method, field) Properties that are marked with this annotation will be "unwrapped", that is, properties that would normally be written as properties of a child JSON Object are instead added as properties of enclosing JSON Object.

Categories

Resources