Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson: is it possible to include property of parent object into nested object?

I'm using Jackson to serialize/deserialize JSON objects.

I have the following JSON for a Study object:

{
    "studyId": 324,
    "patientId": 12,
    "patient": {
        "name": "John",
        "lastName": "Doe"
    }
}

UPDATE: Unfortunately the JSON structure cannot be modified. It's part of the problem.

I would like to deserialize the object to the following classes:

public class Study {
    Integer studyId;
    Patient patient;
}

and

public class Patient {
    Integer patientId;
    String name;
    String lastName;
}

Is it possible to include the patientId property in the Patient object?

I am able to deserialize the patient object into the Patient class (with the corresponding name and lastName properties), but unable to include the patientId property.

Any ideas?

like image 355
monsieurBelbo Avatar asked Mar 23 '23 04:03

monsieurBelbo


2 Answers

You can use a custom deserializer for your use case. Here is what it will look like:

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;

public class StudyDeserializer extends JsonDeserializer<Study>
{
    @Override
    public Study deserialize(JsonParser parser, DeserializationContext context)
        throws IOException, JsonProcessingException
    {
        JsonNode studyNode = parser.readValueAsTree();

        Study study = new Study();
        study.setStudyId(studyNode.get("studyId").asInt());

        Patient patient = new Patient();
        JsonNode patientNode = studyNode.get("patient");
        patient.setPatientId(studyNode.get("patientId").asInt());
        patient.setName(patientNode.get("name").asText());
        patient.setLastName(patientNode.get("lastName").asText());
        study.setPatient(patient);

        return study;
    }
}

Specify the above class as your deserializer in the Study class:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

@JsonDeserialize(using = StudyDeserializer.class)
public class Study
{
    Integer studyId;
    Patient patient;

    // Getters and setters
}

Now, the JSON input you have specified should get deserialized as expected.

like image 116
Jackall Avatar answered Apr 06 '23 04:04

Jackall


There is no declarative way to do such object transformation: you are transforming structure between JSON and POJOs. Jackson's support in this area is limited by design: two things are out of scope: validation (use external validation; Bean Validation API or JSON Schema validator) and transformations (can use JsonNode or external libraries).

like image 43
StaxMan Avatar answered Apr 06 '23 02:04

StaxMan