json - 无法使用 Jackson ObjectMapper 将 Json 序列化为 Java 对象
问题描述
我正在编写一个可以导出/导入数据的 Java spring boot mvc 应用程序。我写了一个包装类,应该为学生类序列化/反序列化数据。它适用于导出,但在导入过程中出现错误
com.fasterxml.jackson.databind.exc.MismatchedInputException: Root name
'student' does not match expected ('students') for type [simple type,
class org.bajiepka.courseApp.wrappers.Response] at [Source:
(FileInputStream); line: 2, column: 3]
这是我的 maven jackson 依赖项:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
我使用包装类 Response 作为学生列表,
package org.bajiepka.courseApp.wrappers;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRootName;
import org.bajiepka.courseApp.domain.Student;
@JsonRootName("import")
public class Response {
private Iterable<Student> students;
@JsonProperty("students")
public Iterable<Student> getStudents(){
return students;
}
public void setStudents(Iterable<Student> students) {
this.students = students;
}
}
这是我的学生课:
@Data
@Entity
public class Student {
private @Id @GeneratedValue Long id;
private @Version int version;
@NotNull
private String name;
private String address;
private String phone;
private Integer gradeBook;
private float averageProgress;
public Student() {}
}
}
这是创建导出文件的方法:
public String write(boolean toFile){
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
ObjectWriter writer = mapper.writer().withDefaultPrettyPrinter();
try {
String result = writer.writeValueAsString(response);
if (toFile){
result = fileService.writeToFile(result);
}
return result;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return "";
}
导出后,我得到了带有 json 的文件,我无法转换为 java 对象:
{
"student" : [ {
"id" : 1,
"version" : 0,
"name" : "Rachel Jessica Parker",
"address" : "Pentaho",
"phone" : "111-22-33",
"gradeBook" : 1000121,
"averageProgress" : 0.0
}, {
"id" : 2,
"version" : 0,
"name" : "Bobby Jackson Junior",
"address" : "Illinois",
"phone" : "222-33-44",
"gradeBook" : 1000122,
"averageProgress" : 0.0
}, {
"id" : 3,
"version" : 0,
"name" : "Sammy Smith Carlson",
"address" : "Pennsylvania",
"phone" : "333-44-55",
"gradeBook" : 1000123,
"averageProgress" : 0.0
}, {
"id" : 4,
"version" : 0,
"name" : "Harry Dale Harrison",
"address" : "Detroit",
"phone" : "444-55-66",
"gradeBook" : 1000124,
"averageProgress" : 0.0
}, {
"id" : 5,
"version" : 0,
"name" : "Lindsey jefferson Conly",
"address" : "Washington",
"phone" : "555-66-77",
"gradeBook" : 1000125,
"averageProgress" : 0.0
}, {
"id" : 6,
"version" : 0,
"name" : "Mo Williams Jr.",
"address" : "New York",
"phone" : "666-77-88",
"gradeBook" : 1000126,
"averageProgress" : 0.0
} ]
}
最后这是转换的方法:
@GetMapping(value = "/import")
public String importFile(@RequestParam Long id){
File importFile = new File(exchangeFileService.findById(id).getName());
if (importFile.exists()) {
try (FileInputStream stream = new FileInputStream(importFile)) {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
TypeReference<Response> typeReference = new TypeReference<>(){};
Response response = mapper.readValue(stream, typeReference);
} catch (IOException e) {
e.printStackTrace();
}
}
return "redirect:/exchange/upload";
}
我在 mapper.readValue(stream, typeReference) 上面提到了 MismatchInputException
ObjectMapper 应该向我返回一个包含学生列表的响应,但它没有...
@更新
我已经设法找到错误的原因。在 Object -> Json serialization jackson root name is missing...期间我手动添加了
{
**"import" : {**
"student" : [ {
"id" : 1,
"version" : 0,
"name" : "Rachel Jessica Parker",
"address" : "Pentaho",
"phone" : "111-22-33",
"gradeBook" : 1000121,
"averageProgress" : 0.0
}, ... ]
,
"course" : [ {
"id" : 7,
"version" : 0,
"name" : "Physics for 9-th grade",
"number" : 100292910,
"cost" : 25000.0,
"modules" : 0,
"max_COURSES_PER_STUDENT" : 3,
"modules_PER_COURSE" : 10
}, ... ]
**}**
}
我还设法扩展了 Response 类,因为它是必需的......现在我试图在序列化期间在 ObjectMapper 中找到原因......
解决方案
该问题是由于 Java 对象 -> 没有根级别的 Json 序列化引起的。要将其添加到 Json,我刚刚通过 withRootName() 方法将其添加到映射器中,从现在开始一切正常!
mapper.writer().withDefaultPrettyPrinter().withRootName("import")
推荐阅读
- javascript - 我不知道如何使用 img 标签显示图像。我正在通过
- file-upload - Laravel上传文件403服务器禁止错误
- android - 添加谷歌服务插件后,我在 build.gradle 中发现了两个错误。如何解决这个错误?
- r - 如何将文件列表读入单个 data.table
- powershell - 将带有集合对象的数据插入 SQL Server 表
- angular - 使用 @Input 和服务可观察订阅进行组件单元测试
- google-kubernetes-engine - Ingress (gce) 是否需要 defaultBackend?
- selenium-webdriver - 需要从 .bat 文件启动一个特殊版本的 FireFox 并为其使用 webdriver
- javascript - 平滑滚动的锚点填满整个页面
- python - 熊猫:df['A'] == df['B'] 或 df['B'] == [] 的行数