Не удается сериализовать Json в объект Java с помощью Jackson ObjectMapper

#json #jackson #objectmapper

#json #джексон #objectmapper

Вопрос:

Я пишу приложение Java spring boot mvc с возможностью экспорта / импорта данных. Я написал класс-оболочку, который должен сериализовать / десериализовать данные для класса Student. Это хорошо работает для экспорта, но во время импорта появляется ошибка

 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>
  

Я использую ответ класса-оболочки для списка студентов,

 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 resu<
    } 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
  } ]
}
  

And finally this is the method for conversion:

 @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";
}
  

я получаю упомянутое выше исключение MismatchInputException в mapper.readValue (поток, ссылка на тип)

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 object -> сериализации Json без корневого уровня. Чтобы добавить его в Json, я только что добавил его в mapper методом withRootName (), и с этого момента все работает хорошо!

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