如何将平面 JSON 转换为分层 java Class?
How to transform a flat JSON to hierarchical java Class?
我需要将平面 JSON 对象反序列化为 Java 对象,并将某些属性设置为子对象。
{
"name": "abcd",
"addressLine1": "123",
"addressLine2": "1111"
}
Class Student {
String name;
Address address;
}
Class Address {
String line1;
String line2;
}
如何使用 Jackson 将我的 JSON 反序列化为 Student
对象?
我无法映射 addressLine1 to Student.Address.line1
和 addressLine2 to Student.Address.line2
首先,确保你的依赖项或库中有 jackson-databind。
您可以执行以下操作:
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());
}
class 对象中的直接反序列化意味着 Class 和 Json 字符串具有完全相同的属性。这不是这里的cas。因此使用 for 进行循环并使用修改器。
阅读this了解更多详情
您可以像这样使用 ObjectMapper:
ObjectMapper objectMapper = new ObjectMapper();
Student student = objectMapper.readValue(json, Student.class);
但是您还必须如下修改 Student class 并实现所有 getter 和 setter:
Class Student{
String name;
String addressLine1;
String addressLine2;
}
然后,如果您愿意,可以根据需要将其重构为新的 class。希望能帮助到你。
编辑:虽然我的解决方案有效,但 Selindek 的回答是最好的
根据 https://jsonlint.com/,您的 Json 无效,原因有两个:
- 您的字段名称未被引用
- 你在最后一行后有一个逗号
我假设这个 JSON,字段名称不带引号:
{
name: "abcd",
addressLine1: "123",
addressLine2: "1111"
}
我可以想到两种方法:
1 - 简单的地图处理
// 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 - 使用代理对象(我更喜欢这个)
另一种方法是拥有一个代理 class,您可以在其中反序列化您的 JSON,并从中构建您的学生:
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
}
并这样使用:
// 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());
}
注意
如果您输入错误并且确实有引用字段,即:
{
"name": "abcd",
"addressLine1": "123",
"addressLine2": "1111"
}
那么你不需要那行
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
您可以这样定义数据类:
public static class Student {
String name;
@JsonUnwrapped
Address address;
}
public static class Address {
@JsonProperty("addressLine1")
String line1;
@JsonProperty("addressLine2")
String line2;
}
然后您可以按常规方式使用 Objectmapper
- 无需任何额外的魔法或解决方法:
Student student = mapper.readValue(json, Student.class);
如果您传入的 json 字符串确实是您提供的格式(不带引号),那么还要添加:
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
我需要将平面 JSON 对象反序列化为 Java 对象,并将某些属性设置为子对象。
{
"name": "abcd",
"addressLine1": "123",
"addressLine2": "1111"
}
Class Student {
String name;
Address address;
}
Class Address {
String line1;
String line2;
}
如何使用 Jackson 将我的 JSON 反序列化为 Student
对象?
我无法映射 addressLine1 to Student.Address.line1
和 addressLine2 to Student.Address.line2
首先,确保你的依赖项或库中有 jackson-databind。
您可以执行以下操作:
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());
}
class 对象中的直接反序列化意味着 Class 和 Json 字符串具有完全相同的属性。这不是这里的cas。因此使用 for 进行循环并使用修改器。
阅读this了解更多详情
您可以像这样使用 ObjectMapper:
ObjectMapper objectMapper = new ObjectMapper();
Student student = objectMapper.readValue(json, Student.class);
但是您还必须如下修改 Student class 并实现所有 getter 和 setter:
Class Student{
String name;
String addressLine1;
String addressLine2;
}
然后,如果您愿意,可以根据需要将其重构为新的 class。希望能帮助到你。
编辑:虽然我的解决方案有效,但 Selindek 的回答是最好的
根据 https://jsonlint.com/,您的 Json 无效,原因有两个:
- 您的字段名称未被引用
- 你在最后一行后有一个逗号
我假设这个 JSON,字段名称不带引号:
{
name: "abcd",
addressLine1: "123",
addressLine2: "1111"
}
我可以想到两种方法:
1 - 简单的地图处理
// 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 - 使用代理对象(我更喜欢这个)
另一种方法是拥有一个代理 class,您可以在其中反序列化您的 JSON,并从中构建您的学生:
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
}
并这样使用:
// 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());
}
注意
如果您输入错误并且确实有引用字段,即:
{
"name": "abcd",
"addressLine1": "123",
"addressLine2": "1111"
}
那么你不需要那行
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
您可以这样定义数据类:
public static class Student {
String name;
@JsonUnwrapped
Address address;
}
public static class Address {
@JsonProperty("addressLine1")
String line1;
@JsonProperty("addressLine2")
String line2;
}
然后您可以按常规方式使用 Objectmapper
- 无需任何额外的魔法或解决方法:
Student student = mapper.readValue(json, Student.class);
如果您传入的 json 字符串确实是您提供的格式(不带引号),那么还要添加:
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);