0

I've the following JSON from some upstream api

{
    "Id": "",
    "Name": "",
    "Age": ""
}

And I need to map this above json to a downstream request paylaod (POJO) .

public class Employee
{
     @JsonProperty("Id")
     private Integer Id;
     private User user;
}

public class User {

     @JsonProperty("Name")
     private String name;

     @JsonProperty("Age")
     private String age;

}

Right now I'm doing something like

Employee employee = new ObjectMapper().treeToValue(JsonNode node,Employee.class);

But this is giving null in User Object.

The challenge here is , that the json we are getting from upstream can't be changed . So , is there is any way to map the fields into the nested User object , without changing the structure of json received from upstream.

One Solution is : map the fields separately into User object and then set it into the Employee object . But that's not an efficient solution , because for null validations we would need to do validations separately for User and Employee objects. If the nesting is complex then , validation will be hell of replicated code .

0

3 Answers 3

3

Your JSON does not comply with your Employee class.

Because name and age is at the same level as id, but you want to wrapped in a class User.

So either:

  1. Change the json the structure to

     {
      "id": "", 
      "user": {
        "name": "", 
        "age": ""
       }
     }
    

Or

  1. Unwrap the User class, the Employee class will be:

     public class Employee
     {
         @JsonProperty("Id")
         private Integer Id;
    
         @JsonProperty("Name")
         private String name;
    
         @JsonProperty("Age")
         private String age;
     }
    

Edit

If you can't choose either option 1 or 2, you have only one option left is to create custom deserializer:

Write a deserializer:

public class EmployeeDeserializer extends StdDeserializer<Item> { 

    public EmployeeDeserializer() { 
        this(null); 
    } 

    public EmployeeDeserializer(Class<?> vc) { 
        super(vc); 
    }

    @Override
    public Employee deserialize(JsonParser jp, DeserializationContext ctxt) 
      throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        int id = (Integer) ((IntNode) node.get("Id")).numberValue();
        String name = node.get("Name").asText();
        String age = node.get("Age")).asText();
        User user = new User(name, age);
        return new Employee(id, user);
    }
}

Then register this deserializer:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Employee.class, new EmployeeDeserializer());
mapper.registerModule(module);

Employee readValue = mapper.readValue(json, Employee.class);

Another way to register deserializer is:

@JsonDeserialize(using = EmployeeDeserializer.class)
public class Employee {
Sign up to request clarification or add additional context in comments.

3 Comments

json received from upstream can't be changed . So , is there is any way to map the fields into the nested User object , without changing the structure of json received from upstream.
You can't change to option 2?
yup , can't change to option 2 , because the request payload for the downstream has a definite structure to which i need to conform .
1

It seems you are not nesting your JSON correctly. Or your Object Structure is wrong.

JSON should be:

{
    "Id": "",
    "user" : {
                "Name": "",
                "Age": ""
    }
}

1 Comment

json received from upstream can't be changed . So , is there is any way to map the fields into the nested User object , without changing the structure of json received from upstream.
0

The json structure does not match the structure of your classes. if the json was like;

{
  "Id": "an-id,
  "user": {
    "Name": "Joe",
    "Age": "21"
  }
}

Then your code to deserialise to an Employee object would work.

2 Comments

json received from upstream can't be changed . So , is there is any way to map the fields into the nested User object , without changing the structure of json received from upstream.
I would always try to match my class structure to the JSON format I want. So your best option here is to have two Employee classes, with appropriate names, one that matches the incoming JSOn and one that matches the downstream JSON, then have a mapper class that maps one to the other, that is not used for serializing or deserializing. Custom Serialization code is usually unnecessary and messy

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.