0
votes

I'm writing a Java spring boot mvc application with possibility of data export / import. I wrote a wrapper class, that shoud serialize / deserialize data for Student class. It works good for export, but during import an error appears

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]

here is my maven jackson dependency:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.8</version>
</dependency>

I use wrapper class Response for list of students,

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

And this is my Student class:

@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() {}
    }
}

This is the method that created an export file:

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

after export i get the file with json, that i can't convert to java objects:

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

i get mentioned above MismatchInputException at mapper.readValue(stream, typeReference)

ObjectMapper should return me a Response with a list of students but it doesn't...

@UPDATE

I've managed to find the cause of the error. During the Object -> Json serialization jackson root name is missed... I've added manually

{
    **"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
          }, ... ]
    **}**
}

Also i've managed to extend Response class, as it was required... Now i'm trying to find the reason in ObjectMapper during serialization...

1

1 Answers

0
votes

The problem was caused due to Java object -> Json serialization without root level. To add it to Json i've just added it at mapper by withRootName() method and everything works well from now on!

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