Search code examples
javajsonjacksonjson-deserialization

Add parent variables inside an json object while deserialize in jackson


I wanted to add extended class variables inside and jsonobject during deserialization in jackson.

ParentResponse Class :

@JsonInclude(value = Include.NON_EMPTY)
public class ParentResponse extends DefaultResponse {

@JsonProperty("parentname")
private String parentName;

// Getter and setter
}

DefaultResponse Class :

@JsonInclude(value = Include.NON_EMPTY)
public class DefaultResponse{

@JsonProperty("status")
private String status;

// Getter and Setter


@JsonProperty("responseInfo")
    public JSONObject responseInfo() {
        JSONObject jsonResponse = new JSONObject();
        jsonResponse.put("status", this.status);
        return new JSONObject();
    }
}
public class ResponseResource {
public static void main(String[] args) {
ParentResponse response = new ParentResponse();
        response.setStatus("success");
System.out.println(new ObjectMapper().writer().withDefaultPrettyPrinter().writeValueAsString(response));
}
}

This returns

{
    "status": "success",
}

My Requirement is

{
"responseInfo" : {
     "status" : "success"
}

Is this possible without customSerializer in jackson ?


Solution

  • Instead of your method responseInfo() you can declare a method returning a single-entry Map that would serve as a getter.

    Note that this method doesn't require any data-binding annotations, it just needs to be named as a conventional getter in order to be treated by Jackson as a getter.

    To avoid duplicating "status" property as a part of the attribute "responseInfo" and as a representation of the status field while serializing DefaultResponse you can either

    • Prevent Jackson accessing it by not exposing a getter (which might be not convenient because you might need a getter).
    • Another way is to annotate the field with @JsonIgnore, that would cause the status to be omitted during both serialization and desrialization.
    • The most flexible solution is to make use of the access attribute of the @JsonProperty annotation because it gives more control. For instance, if assigning access attribute to JsonProperty.Access.WRITE_ONLY it would be taken into account while deserializing JSON, but excluded during serialization.

    That's how it might be implemented:

    @JsonInclude(value = JsonInclude.Include.NON_EMPTY)
    @Setter
    @Getter
    public static class DefaultResponse {
        @JsonProperty(value = "status", access = JsonProperty.Access.WRITE_ONLY)
        private String status;
        
        public Map<String, String> getResponseInfo() {
            return Map.of("status", status);
        }
    }
    

    Usage example:

    public static void main(String[] args) throws JsonProcessingException {
        ParentResponse response = new ParentResponse();
        response.setStatus("success");
        
        String jsonResponse = new ObjectMapper().writer()
            .withDefaultPrettyPrinter()
            .writeValueAsString(response);
        
        System.out.println(jsonResponse);
    }
    

    Output:

    {
      "responseInfo" : {
        "status" : "success"
      }
    }