Xamarin Essentials Preferences存列表触发JsonReaderException异常
根因定位
你遇到的解析异常完全由SavedList属性的get访问器默认值设计不合理导致,触发逻辑和报错信息完全匹配:
Preferences.Get(nameof(SavedList), "test")的运行逻辑是:当本地偏好存储中没有对应key的记录时,会直接返回你传入的默认字符串"test"。后续代码会把这个字符串直接传入Deserialize<List<string>>做JSON反序列化。- 由于
"test"不是合法的JSON结构,Newtonsoft.Json解析器逐字符扫描时,遇到首字符t会优先判定为布尔值true的起始字符,扫描到第一个位置发现内容不匹配布尔值格式,就会抛出Error parsing boolean value. Path '', line 1, position 1.的异常。 - 额外的触发场景:如果历史版本的代码曾用同一个key
"SavedList"存储过布尔类型的值,后续读取时Preferences取出的会是布尔值的字符串形式(如"True"),同样会因为首字符为t触发相同的解析报错。 - 这套逻辑下根本走不到SavedList返回null的分支,因为异常在反序列化阶段就已经抛出,后续的空值判断逻辑完全不会执行,你感知到的“返回null”本质是未处理异常中断了流程。
修复方案
- 修正get访问器的默认值取值逻辑,不要传入无JSON结构的纯文本作为默认返回值,同时增加反序列化的异常兜底,避免脏值导致应用崩溃:
public static List<string> SavedList { get { // 读取原始存储值,无值时返回空字符串 var storedRaw = Preferences.Get(nameof(SavedList), string.Empty); // 空值直接返回空列表,跳过无意义的反序列化 if (string.IsNullOrWhiteSpace(storedRaw)) return new List<string>(); // 增加异常捕获,处理历史遗留的脏值 try { var savedList = JsonConvert.DeserializeObject<List<string>>(storedRaw); return savedList ?? new List<string>(); } catch (JsonReaderException) { // 清理无法解析的脏值,避免后续重复报错 Preferences.Remove(nameof(SavedList)); return new List<string>(); } } set { var serializedList = JsonConvert.SerializeObject(value); Preferences.Set(nameof(SavedList), serializedList); } } - 统一同一个key下的存储类型,不要在
"SavedList"这个key下存非序列化的纯文本、其他值类型(如bool、int),避免不同版本的代码读写时出现类型不匹配。 - 序列化列表得到的JSON字符串本身是合法格式(形如
["value1","value2"]),只要保证读取流程不会拿到非序列化的纯文本,就可以正常完成读写流程。
内容的提问来源于stack exchange,提问作者avava
相关产品推荐
相关产品推荐

