问题
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?
回答1:
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.
回答2:
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).
回答3:
Depending on how stable this format is (and in what mood your QA guy is) you could alter the Json directly before passing it to Jackson. This would be fixing what is broken. Regex would be one idea. Reading it in a Hashmap, moving the value there and writing it out as fixed Json another. But even more simple in pseudocode:
String json = "...";
String lines = json.split( "\r" );
swap( lines[2], lines[3] ); //*1
String fixed = join( lines ); //*2
where
*1: tmp = lines[2]; lines[2] = lines[3]; lines[3] = tmp;
*2: http://stackoverflow.com/questions/1515437/java-function-for-arrays-like-phps-join
(if I had to take this route I would use the hashmap aproach)
回答4:
You have your patientId stored outside of your patient object. Put it in and everything is shiny ;)
If you insist on putting it exactly there in the json I'm afraid you are in trouble. (Best would be to convince the Json designer to store it where it belongs which is in the Patient object as you have it in Java.)
If nothing helps you have to use a Data Transfer Object (https://en.wikipedia.org/wiki/Data_transfer_object) or a custom deserializer (Setting up JSON custom deserializer) in order to translate between the sane and insane representations.
来源:https://stackoverflow.com/questions/19191223/jackson-is-it-possible-to-include-property-of-parent-object-into-nested-object