无法使用 Jackson ObjectMapper 将 Json 序列化为 Java 对象

Posted

技术标签:

【中文标题】无法使用 Jackson ObjectMapper 将 Json 序列化为 Java 对象【英文标题】:Can't serialize Json to Java object using Jackson ObjectMapper 【发布时间】:2019-08-21 23:12:30 【问题描述】:

我正在编写一个可以导出/导入数据的 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 应该向我返回一个包含学生列表的响应,但它没有...

@UPDATE

我已经设法找到了错误的原因。 在 Object -> Json 序列化期间,缺少 jackson 根名称... 我已经手动添加了


    **"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 中找到原因......

【问题讨论】:

【参考方案1】:

问题是由于Java对象->没有根级别的Json序列化引起的。 要将其添加到 Json,我刚刚通过 withRootName() 方法将其添加到 mapper,从现在开始一切正常!

mapper.writer().withDefaultPrettyPrinter().withRootName("import")

【讨论】:

以上是关于无法使用 Jackson ObjectMapper 将 Json 序列化为 Java 对象的主要内容,如果未能解决你的问题,请参考以下文章

理解异常的麻烦:“无法从 START_OBJECT 令牌中反序列化 `java.lang.String` 的实例”在 Jackson 中使用 ObjectMapper

Spring Boot 不使用配置的 Jackson ObjectMapper 和 @EnableWebMvc

Jackson ObjectMapper 无法反序列化 POJO,抛出异常:没有找到适合类型 [...] 的构造函数:无法从 JSON 对象实例化

Jackson ObjectMapper类使用解析

jackson中objectMapper的使用

ObjectMapper类