You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用单个Flutter模型同时适配Isar数据库与JsonSerializable?

解决Isar与JsonSerializable关联类型冲突的单变量方案

你遇到的双变量冗余问题确实影响代码整洁度,其实可以通过自定义Json转换器实现单个变量同时适配Isar和JsonSerializable,无需维护两套字段。

核心思路

自定义JsonConverter,让JsonSerializable直接处理IsarLink<T>类型:

  • 序列化(toJson):提取IsarLink的value转为JSON对象
  • 反序列化(fromJson):将JSON对象转为目标类型,赋值给IsarLink的value

具体实现

1. 编写通用IsarLink转换器

import 'package:isar/isar.dart';
import 'package:json_annotation/json_annotation.dart';

class IsarLinkConverter<T> implements JsonConverter<IsarLink<T>, dynamic> {
  const IsarLinkConverter();

  @override
  IsarLink<T> fromJson(dynamic json) {
    final link = IsarLink<T>();
    if (json != null) {
      // 关联类需实现fromJson工厂方法
      link.value = json is T ? json : _parseFromJson<T>(json);
    }
    return link;
  }

  @override
  dynamic toJson(IsarLink<T> link) => link.value?.toJson();

  // 适配不同关联类的fromJson调用,可按需扩展类型判断
  T _parseFromJson<T>(Map<String, dynamic> json) {
    switch (T.toString()) {
      case 'Organization':
        return Organization.fromJson(json) as T;
      case 'Domain':
        return Domain.fromJson(json) as T;
      case 'UserGroupPermissions':
        return UserGroupPermissions.fromJson(json) as T;
      default:
        throw UnsupportedError('未支持的类型: $T');
    }
  }
}

2. 改造UserGroup模型

移除冗余的普通类型字段,直接用IsarLink并绑定转换器注解:

@Collection()
@JsonSerializable()
class UserGroup {
  @JsonKey(ignore: true)
  Id localId = Isar.autoIncrement;

  @JsonKey(name: "_id")
  String? id;

  String name;
  String description;

  @JsonKey(converter: IsarLinkConverter<Domain>())
  final IsarLink<Domain> domain = IsarLink<Domain>();

  @JsonKey(converter: IsarLinkConverter<UserGroupPermissions>())
  final IsarLink<UserGroupPermissions> permissions = IsarLink<UserGroupPermissions>();

  @JsonKey(converter: IsarLinkConverter<Organization>())
  final IsarLink<Organization> organization = IsarLink<Organization>();

  UserGroup({
    this.id,
    required this.name,
    required this.description,
    Domain? domain,
    UserGroupPermissions? permissions,
    Organization? organization,
  }) {
    // 构造函数中初始化IsarLink的初始值
    if (domain != null) this.domain.value = domain;
    if (permissions != null) this.permissions.value = permissions;
    if (organization != null) this.organization.value = organization;
  }

  factory UserGroup.fromJson(Map<String, dynamic> json) => _$UserGroupFromJson(json);
  Map<String, dynamic> toJson() => _$UserGroupToJson(this);
}

注意事项

  • 所有关联类(如Organization、Domain)必须实现fromJson和toJson方法
  • 若项目中关联类较多,可通过反射简化转换器的类型判断(需添加reflectable依赖并配置)
  • IsarLink必须在类中初始化(如final+默认值或late修饰),否则Isar会抛出初始化错误

内容的提问来源于stack exchange,提问作者Jishnu Raj

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:50:36