Android SharedPreferences反序列化SearchAvailableRidesRequestOffline遇Jackson异常
解决Jackson反序列化MismatchedInputException(期望START_ARRAY却得到START_OBJECT)
这个Jackson反序列化的坑我之前也踩过!异常信息说得很明确:Jackson期望拿到一个JSON数组(START_ARRAY),但实际读到的是一个JSON对象(START_OBJECT),根源是你的序列化/反序列化配置和实际存储的JSON格式不匹配,下面给你几种针对性的解决思路:
1. 如果你只需要存储单个对象(不需要数组包裹)
这种情况最常见——你存的是SearchAvailableRidesRequestOffline的单个实例,但Jackson的反序列化配置要求用WRAPPER_ARRAY(数组包裹)来携带类型信息。
调整Jackson配置,去掉数组包裹要求:
检查你的ObjectMapper初始化代码,如果有类似下面的配置:
ObjectMapper mapper = new ObjectMapper(); // 这个配置会要求用数组包裹对象来携带类型信息 mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
改成以下两种方式之一:
- 不需要类型信息时:直接用默认配置
ObjectMapper mapper = new ObjectMapper(); // 可以加上一些常用配置,比如忽略未知字段 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - 需要类型信息但用对象包裹:把
WRAPPER_ARRAY改成WRAPPER_OBJECT
这种配置下,序列化后的JSON会带一个ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_OBJECT);@class字段标记类型,反序列化时就能正确识别子类。
2. 如果你确实需要用数组包裹(比如兼容多实例场景)
如果你的业务逻辑要求用数组存储(比如未来可能存多个请求),那需要序列化和反序列化都统一用数组格式:
序列化时把对象放到数组/List中:
SearchAvailableRidesRequestOffline request = new SearchAvailableRidesRequestOffline(); // 把单个对象包装成List List<SearchAvailableRidesRequestOffline> requestList = Collections.singletonList(request); // 序列化为JSON字符串 String json = mapper.writeValueAsString(requestList); // 存入SharedPreferences sharedPreferences.edit().putString("RIDE_REQUEST_KEY", json).apply();
反序列化时读取数组/List:
String savedJson = sharedPreferences.getString("RIDE_REQUEST_KEY", null); if (savedJson != null) { // 用TypeReference指定List的泛型类型 List<SearchAvailableRidesRequestOffline> requestList = mapper.readValue( savedJson, new TypeReference<List<SearchAvailableRidesRequestOffline>>() {} ); // 取出第一个对象(因为你存的是单个) SearchAvailableRidesRequestOffline request = requestList.get(0); // 后续业务逻辑处理 }
3. 先确认SharedPreferences中存储的JSON格式
可以先打印出SharedPreferences里的JSON字符串,确认实际存储的是单个对象(比如{"request": {...}, "filterType": ...})还是数组(比如[{"request": {...}, "filterType": ...}]):
Log.d("JSON_DEBUG", sharedPreferences.getString("RIDE_REQUEST_KEY", "EMPTY"));
这样能快速定位是序列化时的格式问题,还是反序列化时的配置问题。
内容的提问来源于stack exchange,提问作者Siddharth
相关产品推荐
相关产品推荐

