spring boot - com.fasterxml.jackson.databind.JsonMappingException:无法从START_OBJECT中反序列化java.util.ArrayList的实例

时间:2017-11-21 22:55:08

标签: java json spring-boot arraylist jackson

我想做什么:

将ArrayList发送到我的spring启动应用程序并进行处理。我可以通过自己的方法做到这一点,但似乎方法不合适。 (请在此页面上看到该部分搜索此内容:"此部分不合适")

什么是我的ArrayList:

{
  "takeCourseModels": [
    {
      "courseId": "8",
      "userId": "12"
    },
    {
      "courseId": "7",
      "userId": "12"
    }
  ]
}

我得到的(错误):

"Could not read document: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token\n at line: 1, column: 1; nested exception is com.fasterxml.jackson.databind.JsonMappingException"

在Google上搜索此问题后我学到了什么:

•我需要反序列化我的arraylist,因为这个arraylist不是JSON Array。这就是它无法阅读的原因 •我需要使用ObjectMapper和其他类来接收它,例如:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(SomeModel.class, new ProgramDeserializer());

String jsonStr = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(jsonStr);
myObjClass[] objects = mapper.readValue(rootNode.toString(), myObjClass[].class);

•问题是我没有自定义反序列化类(必须有一些默认类)并且我不知道如何将自定义反序列化类集成到我的应用程序中。此外,我有多个端点,其中包括需要反序列化的arraylist,所以我不知道如何创建可用于各种模型的模块化反序列化类。 (下面,我只显示课程模型,还有其他模型需要包含反序列化类)

应用类:

所有MyApplication

@SpringBootApplication  
public class MyApplication {

   @Bean
   public FilterRegistrationBean jwtFilter() {
       final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
       registrationBean.setFilter(new JwtFilter());
       registrationBean.addUrlPatterns("/api/*");

       return registrationBean;
   }

   public static void main(String[] args) {
       SpringApplication.run(MyApplication.class, args);
    }
 }  

CustomWebMvcAutoConfig

@Configuration
@AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
public class CustomWebMvcAutoConfig extends WebMvcConfigurerAdapter {

   @Override
   public void configureMessageConverters(List<HttpMessageConverter<?>converters) {
       for (HttpMessageConverter converter : converters) {
           if (converter instanceof org.springframework.http.converter.json.MappingJackson2HttpMessageConverter) {
               ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
               mapper.registerModule(new Hibernate4Module());
           }
       }
   }

   @Override
   public void extendMessageConverters(List<HttpMessageConverter<?>converters) {
       converters.add(mappingJackson2HttpMessageConverter());
   }

   @Bean
   public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
       MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
       converter.setObjectMapper(new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false));
       return converter;
   }
}  

CourseController

@Controller  
@RequestMapping("/api/")  
@SuppressWarnings("unchecked")  
public class CourseController {

   @Autowired
   private ICourseService courseService;

   //@PostMapping("take_course")
   //public ResponseEntity<VoidtakeCourse(@RequestBody ArrayList<UserCourseuserCourseList) throws EntityNotFoundException {
   @PostMapping("take_course")
   public ResponseEntity<VoidtakeCourse(@RequestBody String json) throws EntityNotFoundException {

   //***(START)THIS PART IS NOT PROPER, I WANT TO DO THE FASTER METHOD***
        ArrayList<UserCourseuserCourseList = new ArrayList<>();
       ObjectMapper mapper = new ObjectMapper();

       JSONObject jsnobject = new JSONObject(json);
       JSONArray jsonArray = jsnobject.getJSONArray("takeCourseModels");
       for (int i = 0; i < jsonArray.length(); i++) {
           JSONObject explrObject = jsonArray.getJSONObject(i);
           UserCourse userCourse = new UserCourse();
           userCourse.setCourseId(Integer.valueOf(explrObject.getString("courseId")));
           userCourse.setUserId(Integer.valueOf(explrObject.getString("userId")));
           userCourse.setIsRegistered("0");
           userCourseList.add(userCourse);
       }
   //***(END) THIS PART IS NOT PROPER, I WANT TO DO THE FASTER METHOD***

       int flag = courseService.takeCourse(userCourseList);
     if(flag == 2){
           return new ResponseEntity(new ResponseCourse("full", "0"), HttpStatus.OK);
       }
       return new ResponseEntity(new ResponseCourse("added.", "1"), HttpStatus.OK);
   }
}

ICourseService

public interface ICourseService {  
  int takeCourse(List<UserCourseuserCourseList);
}

课程服务

@Service
public class CourseService implements ICourseService {

    @Autowired
    private ICourseDAO courseDAO;

    @Override
    public int takeCourse(List<UserCourseuserCourseList) {

        int flag = 2;

        for (int i = 0; i < userCourseList.size(); i++) {
            if (courseDAO.isUserRegisteredToCourse(userCourseList.get(i))) {
                flag = 0;
            } else {
                courseDAO.takeCourse(userCourseList.get(i));
                flag = 1;
            }
        }

        return flag;
    }
}

@Entity  
@Table(name = "courses")  
@JsonIgnoreProperties("inspection")  
public class Course implements Serializable {

   private static final long serialVersionUID = 1L;

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "course_id")
   private int courseId;

   @Column(name = "course_name")
   private String courseName;

   @Column(name = "course_code")
   private String courseCode;

   @Column(name = "number_of_users")
   @ColumnDefault("0")
   private String numberOfUsers;

   @ManyToOne
   @JoinColumn(name = "adminId")
   private Admin admin;

   @ManyToMany
   @JsonIgnore
   @JoinTable(name = "user_course",
           joinColumns = @JoinColumn(name = "course_id", referencedColumnName = "course_id"),
           inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "user_id"))
   private List<UseruserList;

   public String getNumberOfUsers() {
       return numberOfUsers;
   }

   public void setNumberOfUsers(String numberOfUsers) {
       this.numberOfUsers = numberOfUsers;
   }

   public List<UsergetUserList() {
       return userList;
   }

   public void setUserList(List<UseruserList) {
       this.userList = userList;
   }

   public Admin getAdmin() {
       return admin;
   }

   public void setAdmin(Admin admin) {
       this.admin = admin;
   }

   public int getCourseId() {
       return courseId;
   }

   public void setCourseId(int courseId) {
       this.courseId = courseId;
   }

   public String getCourseName() {
       return courseName;
   }

   public void setCourseName(String courseName) {
       this.courseName = courseName;
   }

   public String getCourseCode() {
       return courseCode;
   }

   public void setCourseCode(String courseCode) {
       this.courseCode = courseCode;
   }
}

1 个答案:

答案 0 :(得分:1)

Spring应该能够使用看起来像这样的类来处理反序列化(添加getter和setter):

class UserCourseList {
    private List<UserCourse> takeCourseModels;
}

class UserCourse {
    private long userId;
    private long courseId;
}

以及控制器中的处理方法:

@PostMapping("take_course")
public ResponseEntity<Void> takeCourse(@RequestBody UserCourseList userCourseList) throws 
    EntityNotFoundException {

请注意,示例中的JSON不是JSON数组,它是一个JSON对象,其字段是JSON数组。这基本上是异常告诉你的。创建一个包装类UserCourseList来表示这个JSON是处理这种情况的最有效的方法。