jsonjacksonrest-assuredfasterxml

How to retrieve field value from json object when object name has DOT in it


I want to extract "msg" value from below json using fasterxml.jackson - Can anyone suggest me how my model class should look like?

{
    "statusCode": 422,
    "error": "Unprocessable Entity",
    "message": "Bad data received",
    "err_data": {
        "payment_details.type": {
            "location": "body",
            "param": "payment_details.type",
            "msg": "Must be either etransfer or cheque"
        }
    }
}

This is what I have done, but it is always returning "null" !

@JsonInclude(JsonInclude.Include.ALWAYS)
public class MyApiResponse extends ParentResponse implements Serializable {
    private static final long serialVersionUID = 1L;

    @JsonProperty("payment_details")
    private PaymentDetails payment_details;

    @JsonProperty("payment_details")
    public PaymentDetails getPayment_details() {
        return payment_details;
    }

    @JsonProperty("payment_details")
    public void setPayment_details(PaymentDetails payment_details) {
        this.payment_details = payment_details;
    }
}

ParentResponse model class extends ErrorResponse model class and this is how it looks like..

This ErrorResponse model represents above mentioned JSON.

@JsonInclude(JsonInclude.Include.NON_NULL)
public class ErrorResponse implements Serializable {

    private static final long serialVersionUID = 1L;

    @JsonProperty("statusCode")
    private int statusCode;

    @JsonProperty("error")
    private String error;

    @JsonProperty("message")
    private String message;

    @JsonProperty("err_data")
    private ErrData err_data;

    @JsonProperty("statusCode")
    public int getStatusCode() {
        return statusCode;
    }

    @JsonProperty("statusCode")
    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }

    @JsonProperty("message")
    public String getMessage() {
        return message;
    }

    @JsonProperty("message")
    public void setMessage(String message) {
        this.message = message;
    }

    @JsonProperty("error")
    public String getError() {
        return error;
    }

    @JsonProperty("error")
    public void setError(String error) {
        this.error = error;
    }

    @JsonProperty("err_data")
    public ErrData getErr_data() {
        return err_data;
    }

    @JsonProperty("err_data")
    public void setErr_data(ErrData err_data) {
        this.err_data = err_data;
    }
}

err_data object is represented by below model class.

@JsonInclude(JsonInclude.Include.ALWAYS)
public class ErrData implements Serializable {

    private static final long serialVersionUID = 1L;

    @JsonProperty("email")
    private Email email;

    @JsonProperty("payment_details.type")
    private PaymentDetailsType payment_details_type;

    @JsonProperty("email")
    public Email getEmail() {
        return email;
    }

    @JsonProperty("email")
    public void setEmail(Email email) {
        this.email = email;
    }

    @JsonProperty("payment_details.type")
    public PaymentDetailsType getPayment_details_type() {
        return payment_details_type;
    }

    @JsonProperty("payment_details.type")
    public void setPayment_details_type(PaymentDetailsType payment_details_type) {
        this.payment_details_type = payment_details_type;
    }
}

payment_details.type object represented by below class.

@JsonInclude(JsonInclude.Include.ALWAYS)
public class PaymentDetailsType extends ErrorMessage implements Serializable {

    private static final long serialVersionUID = 1L;

}

@JsonInclude(JsonInclude.Include.ALWAYS)
public class Email extends ErrorMessage implements Serializable {

    private static final long serialVersionUID = 1L;

}

And finally ErrorMessage which is extended by PaymentDetailsType as below.

@JsonPropertyOrder({"location", "param", "value", "msg"})
public class ErrorMessage implements Serializable {

    private static final long serialVersionUID = 1L;

    @JsonProperty("location")
    private String location;

    @JsonProperty("param")
    private String param;

    @JsonProperty("value")
    private String value;

    @JsonProperty("msg")
    private String msg;

    @JsonProperty("location")
    public String getLocation() {
        return location;
    }

    @JsonProperty("location")
    public void setLocation(String location) {
        this.location = location;
    }

    @JsonProperty("param")
    public String getParam() {
        return param;
    }

    @JsonProperty("param")
    public void setParam(String param) {
        this.param = param;
    }

    @JsonProperty("value")
    public String getValue() {
        return value;
    }

    @JsonProperty("value")
    public void setValue(String value) {
        this.value = value;
    }

    @JsonProperty("msg")
    public String getMsg() {
        return msg;
    }

    @JsonProperty("msg")
    public void setMsg(String msg) {
        this.msg = msg;
    }
}

And finally I am trying to get "msg" field value as below -

new Gson().fromJson(response.asString(), MyApiResponse.class).getErr_data().getPayment_details_type().getMsg();

I think there is something wrong with this one - Not sure how to define getter method if field name in json as . (dot).

@JsonProperty("payment_details.type")
public PaymentDetailsType getPayment_details_type() {
    return payment_details_type;
}

Similar to above, I am doing it for below json to retrieve "msg" value and it is working fine.

{
    "statusCode": 422,
    "error": "Unprocessable Entity",
    "message": "Bad data received",
    "err_data": {
        "email": {
            "location": "body",
            "param": "email",
            "value": "test @ com",
            "msg": "Must be a valid email"
        }
    }
}

This is returning correct "msg" value.

new Gson().fromJson(response.asString(), MyApiResponse.class).getErr_data().getEmail().getMsg();

Please suggest!

Thank you.


Solution

  • Here is a minimal example showing how to parse a JSON with Jackson, where the property names may contain dots:

    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import java.io.IOException;
    
    class Main {
        public static void main(String[] args) throws IOException {
            String json = "{" +
                          "    \"payment_details.type\": {" +
                          "        \"location\": \"body\"" +
                          "    }" +
                          "}";
            ObjectMapper mapper = new ObjectMapper();
            Response response = mapper.readValue(json, Response.class);
            System.out.println(response.getPaymentDetailsType().getLocation());
        }
    }
    
    class Response {
        @JsonProperty("payment_details.type")
        private PaymentDetailsType paymentDetailsType;
    
        public PaymentDetailsType getPaymentDetailsType() { return paymentDetailsType; }
    }
    
    class PaymentDetailsType {
        private String location;
    
        public String getLocation() { return location; }
    }
    

    Note that you only need @JsonProperty when the expected property name in JSON cannot be deduced from a setter or variable name