You need to enable JavaScript to run this app. 序列化Realm对象为JSON时抛出Newtonsoft.Json.JsonSerializationException
优惠活动
大模型
产品
解决方案
定价
更多

序列化Realm对象为JSON时抛出Newtonsoft.Json.JsonSerializationException

异常触发根因
  • Realm生成的托管对象是动态代理类型,所有属性访问都绑定对象创建时的Realm数据库上下文与对应线程,跨线程读取属性值会直接抛出底层异常,被Newtonsoft.Json捕获后就会提示“读取属性值时出错”
  • Newtonsoft.Json默认没有内置MongoDBObjectId类型的序列化逻辑,直接序列化该类型会因为无法解析内部结构抛出序列化错误
  • 原代码将序列化逻辑放入Task.Run的后台线程执行,直接触发了Realm对象的线程亲和性限制,是本次报错的直接诱因
修复方案
  • 杜绝直接序列化Realm托管代理对象:在获取Realm对象的当前线程,手动将各属性值映射到无Realm依赖的纯内存DTO类中,从根源上规避代理对象的上下文绑定问题
  • 对主键类型做适配转换:将可空的ObjectId类型转为字符串存入DTO,适配Newtonsoft.Json的默认序列化规则
  • 取消不必要的后台线程序列化操作:纯POCO对象的序列化计算量极低,不需要放入后台线程执行,避免多余的线程切换触发访问异常

代码实现参考

  1. 定义跨页面传输用的纯DTO类
public class ProductDetailDto
{
    public string Id { get; set; }
    public string Brand { get; set; }
    public string ImageUrl { get; set; }
    public string Name { get; set; }
}
  1. 调整原事件方法的序列化逻辑
async void OnItemSelected(product item)
{
    if (item == null)
        return;

    var model = await ProductService.GetProduct(item.Id);

    // 在当前线程完成Realm对象的属性值提取
    var detailDto = new ProductDetailDto
    {
        Id = model.Id?.ToString(),
        Brand = model.Brand,
        ImageUrl = model.ImageUrl,
        Name = model.Name
    };

    // 对无依赖的纯DTO执行序列化
    string jsonStrObj = JsonConvert.SerializeObject(detailDto);

    // 执行页面导航跳转
    await Shell.Current.GoToAsync($"{nameof(ItemDetailPage)}?ProductModel={jsonStrObj}");
}

提示:后续涉及Realm对象的跨线程、跨模块、跨页面传递场景,都需要提前做DTO映射,不要直接传递Realm原生托管对象,避免出现同类的访问异常。

内容的提问来源于stack exchange,提问作者PHULUSO GOVERN RAMULIFHO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.03 04:54:10