问题
I need to deserialize a flat JSON object to a Java object with some properties set to child object.
{
"name": "abcd",
"addressLine1": "123",
"addressLine2": "1111"
}
Class Student {
String name;
Address address;
}
Class Address {
String line1;
String line2;
}
How do I deserialize my JSON using Jackson into a Student
object?
I am not able to map addressLine1 to Student.Address.line1
and addressLine2 to Student.Address.line2
回答1:
You can define your data classes this way:
public static class Student {
String name;
@JsonUnwrapped
Address address;
}
public static class Address {
@JsonProperty("addressLine1")
String line1;
@JsonProperty("addressLine2")
String line2;
}
Then you can use the Objectmapper
in the usual way - without any additional magic or workaround :
Student student = mapper.readValue(json, Student.class);
If your incoming json string is indeed in the format you provided (without quotes) then also add:
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
回答2:
EDIT: While my solutions work, Selindek's answer is best
Your Json is not valid according to https://jsonlint.com/ for 2 reasons:
- Your field names are not quoted
- You have a comma after the last line
I will assume this JSON, with unquoted field names:
{
name: "abcd",
addressLine1: "123",
addressLine2: "1111"
}
I can think of 2 approaches:
1 - Straightforward Map processing
// Create your mapper, and configure it to allow unquoted field names
ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// Parse the JSON to a Map
TypeReference<HashMap<String, String>> typeRef
= new TypeReference<HashMap<String, String>>() {};
Map<String, String> jsonAsMap = null;
try {
jsonAsMap = mapper.readValue(yourJsonString, typeRef);
} catch (Exception e) {
System.out.println("Something went wrong:" + e.getMessage());
}
// Read the data from the map and build your objects
Student student = null;
if(jsonAsMap != null) {
Address address = new Address();
address.setLine1(jsonAsMap.get("addressLine1"));
address.setLine2(jsonAsMap.get("addressLine2"));
student = new Student();
student.setName(jsonAsMap.get("name"));
student.setAddress(address);
System.out.println(student.getName());
System.out.println(student.getAddress().getLine1());
System.out.println(student.getAddress().getLine2());
}
2 - Using a Proxy object (I would prefer this one)
An other approach would be to have a proxy class in which you can deserialize your JSON, and build your student from it:
class RawStudent {
private String name, addressLine1, addressLine2;
public Student toStudent() {
Address address = new Address();
address.setLine1(addressLine1);
address.setLine2(addressLine2);
Student student = new Student();
student.setName(name);
student.setAddress(address);
return student;
}
// GETTERS / SETTERS
}
And use it this way:
// Create your mapper, and configure it to allow unquoted field names
ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// Parse the JSON to a RawStudent object
RawStudent rawStudent = null;
try {
rawStudent = mapper.readValue(jsonUnquoted, RawStudent.class);
} catch (Exception e) {
System.out.println("Something went wrong:" + e.getMessage());
}
// Read the data from the map and build your objects
Student student = null;
if (rawStudent != null) {
student = rawStudent.toStudent();
System.out.println(student.getName());
System.out.println(student.getAddress().getLine1());
System.out.println(student.getAddress().getLine2());
}
NOTE
If you mistyped and indeed have quoted fields, ie:
{
"name": "abcd",
"addressLine1": "123",
"addressLine2": "1111"
}
Then you don't need that line
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
回答3:
Prior everything, make sure you have jackson-databind in your dependencies or libraries.
Here is what you can do :
String jsonInput = // You JSON String here;
TypeReference<HashMap<String, String>> typeRef
= new TypeReference<HashMap<String, String>>() {};
Map<String, String> map = mapper.readValue(jsonInput, typeRef);
Student student = new Student();
Address address = new Address();
for (Map.Entry<String, String> entry : map.entrySet())
{
if(((String)entry.getKey()).equals("addressLine1")){
student.setName(map.get("name"));
student.setAddress(map.get("addressLine1"));
}
if(((String)entry.getKey()).equals("addressLine2")){
address.setLine1(map.get("addressLine1"));
address.setLine2(map.get("addressLine2"));
}
//System.out.println(entry.getKey() + "/" + entry.getValue());
}
Direct deserialization in a class object would mean the Class and the Json string have the exact same properties. Which is not the cas here. Hence the looping with for and the utilisation of mutators.
Read this for more details
回答4:
You can use ObjectMapper like this:
ObjectMapper objectMapper = new ObjectMapper();
Student student = objectMapper.readValue(json, Student.class);
But you also have to modify the Student class as follows with all the getters and setters implemented:
Class Student{
String name;
String addressLine1;
String addressLine2;
}
Then if you want you can refactor this into a new class as you need. Hope it helps.
来源:https://stackoverflow.com/questions/54386011/how-to-transform-a-flat-json-to-hierarchical-java-class