Flutter JSON转Dart模型插件json2dart_safe的使用

发布于 1周前 作者 yibo5220 来自 Flutter

Flutter JSON转Dart模型插件json2dart_safe的使用

I. 概述

json2dart 是一个Flutter插件集合,提供以下功能:

  1. JSON到Dart模型转换

    • 空安全支持
    • 多字段解析
    • 类型安全转换
    • 默认值处理
  2. SQLite数据库操作

    • 自动生成表结构
    • 完整的CRUD操作
    • 复杂类型支持
    • 批量操作支持
  3. 数据库可视化调试

    • 查看所有数据表
    • 查看表结构
    • 查看表数据
    • SQL语句高亮显示

II. 安装

1. 添加依赖

pubspec.yaml 文件中添加以下依赖:

dependencies:
  # JSON解析基础包
  json2dart_safe: ^1.5.8
  
  # 数据库支持(选择一个)
  json2dart_db: ^latest_version    # 标准版
  json2dart_dbffi: ^latest_version # FFI版(性能更好)
  
  # 数据库查看工具(选择一个)
  json2dart_viewer: ^latest_version    # 标准版
  json2dart_viewerffi: ^latest_version # FFI版

2. 调试工具配置

需要使用 flutter_ume

import 'package:json2dart_viewerffi/json2dart_viewerffi.dart';

void main() {
  PluginManager.instance
    ..register(const DBViewer()) // 注册数据库查看插件
    // ... 其他插件注册
}

III. 基本用法

1. JSON解析

// 从Map解析
Map json = {...};
json.asString("key");     // 获取String,如果为null返回""
json.asInt("key");        // 获取int,如果为null返回0
json.asDouble("key");     // 获取double,如果为null返回0.0
json.asBool("key");       // 获取bool,如果为null返回false
json.asBean<T>("key");    // 解析对象
json.asList<T>("key");    // 解析数组

// 多字段解析
json.asStrings(["name", "user_name"]); // 尝试解析name然后是user_name
json.asInts(["id", "user_id"]);
json.asBools(["is_vip", "vip"]);

2. 错误处理

// 添加错误回调
Json2Dart.instance.addCallback((String error) {
  print("解析错误: $error");
});

// 详细错误信息
Json2Dart.instance.addDetailCallback((String method, String key, Map? map) {
  print("方法: $method, 键: $key, 数据: $map");
});

IV. 使用场景

1. 仅JSON解析

如果你只需要JSON解析功能,只需添加基础包:

dependencies:
  json2dart_safe: ^1.5.8

示例模型:

import 'package:json2dart_safe/json2dart.dart';

class UserModel {
  final String? username;
  final String? nickname;
  final int? age;
  final List<String>? hobbies;

  UserModel({
    this.username,
    this.nickname,
    this.age,
    this.hobbies,
  });

  // JSON序列化
  Map<String, dynamic> toJson() => {
    'username': username,
    'nickname': nickname,
    'age': age,
    'hobbies': hobbies,
  };

  // JSON反序列化
  factory UserModel.fromJson(Map json) {
    return UserModel(
      username: json.asString('username'),
      nickname: json.asString('nickname'),
      age: json.asInt('age'),
      hobbies: json.asList<String>('hobbies'),
    );
  }
}

使用示例:

// 解析JSON
Map<String, dynamic> json = {
  'username': 'test',
  'age': 18,
  'hobbies': ['reading', 'gaming']
};
var user = UserModel.fromJson(json);

// 转换为JSON
Map<String, dynamic> data = user.toJson();

2. 带数据库支持

如果你需要数据库支持,添加完整依赖:

dependencies:
  json2dart_safe: ^1.5.8
  json2dart_db: ^latest_version
  json2dart_viewer: ^latest_version

在这种情况下,你需要:

  1. 让你的Model类继承 BaseDbModel
  2. 实现 primaryKeyAndValue 方法
  3. 创建相应的Dao类

参见下一章的完整示例。

V. 完整示例

1. 模型定义 (user_model.dart)

import 'dart:convert';
import 'package:json2dart_safe/json2dart.dart';

/// 用户信息模型
class UserModel with BaseDbModel {
  // 数据库主键,自增
  int? userId;
  
  // 基础字段
  String? username;
  String? nickname;
  String? avatar;
  int? age;
  double? height;
  bool? isVip;
  DateTime? birthday;
  
  // 复杂类型
  List<String>? hobbies;        // 爱好列表
  List<int>? followingIds;      // 关注用户ID
  Map<String, dynamic>? extra;   // 扩展字段
  
  // 构造函数
  UserModel({
    this.userId,
    this.username,
    this.nickname,
    this.avatar,
    this.age,
    this.height,
    this.isVip,
    this.birthday,
    this.hobbies,
    this.followingIds,
    this.extra,
  });

  // JSON序列化
  Map<String, dynamic> toJson() => {
    'user_id': userId,
    'username': username,
    'nickname': nickname,
    'avatar': avatar,
    'age': age,
    'height': height,
    'is_vip': isVip,
    'birthday': birthday?.millisecondsSinceEpoch,
    'hobbies': hobbies,
    'following_ids': followingIds,
    'extra': extra,
  };

  // JSON反序列化
  factory UserModel.fromJson(Map json) {
    return UserModel(
      userId: json.asInt('user_id'),
      username: json.asString('username'),
      nickname: json.asString('nickname'), 
      avatar: json.asString('avatar'),
      age: json.asInt('age'),
      height: json.asDouble('height'),
      isVip: json.asBool('is_vip'),
      birthday: json.asInt('birthday') != null 
          ? DateTime.fromMillisecondsSinceEpoch(json.asInt('birthday'))
          : null,
      hobbies: json.asList<String>('hobbies'),
      followingIds: json.asList<int>('following_ids'),
      extra: json.asMap('extra'),
    );
  }

  // 静态方法用于数据库操作
  static UserModel toBean(Map json) => UserModel.fromJson(json);

  // 重写toString用于调试
  @override
  String toString() => jsonEncode(toJson());

  // 重写相等运算符
  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is UserModel &&
          runtimeType == other.runtimeType &&
          userId == other.userId;

  @override
  int get hashCode => userId.hashCode;

  // 实现BaseDbModel方法,返回主键和值
  @override
  Map<String, dynamic> get primaryKeyAndValue => {'user_id': userId};
}

2. 数据库操作类 (user_dao.dart)

import 'package:json2dart_db/database/base_dao.dart';
import '../models/user_model.dart';

class UserDao extends BaseDao<UserModel> {
  UserDao() : super('tb_user', UserModel.toBean);

  // 根据用户名查询
  Future<UserModel?> queryByUsername(String username) async {
    List<UserModel> users = await query(
      where: 'username = ?',
      whereArgs: [username],
    );
    return users.isEmpty ? null : users.first;
  }

  // 查询VIP用户
  Future<List<UserModel>> queryVipUsers() async {
    return query(
      where: 'is_vip = ?',
      whereArgs: [1],
      orderBy: 'user_id DESC',
    );
  }

  // 更新用户VIP状态
  Future<bool> updateVipStatus(int userId, bool isVip) async {
    int count = await update(
      {'is_vip': isVip ? 1 : 0},
      where: 'user_id = ?',
      whereArgs: [userId],
    );
    return count > 0;
  }

  // 批量更新关注状态
  Future<void> updateFollowingIds(int userId, List<int> followingIds) async {
    await update(
      {'following_ids': followingIds},
      where: 'user_id = ?',
      whereArgs: [userId],
    );
  }
}

3. 使用示例 (user_page.dart)

import '../database/dao/user_dao.dart';
import '../models/user_model.dart';

class UserPage extends StatefulWidget {
  @override
  _UserPageState createState() => _UserPageState();
}

class _UserPageState extends State<UserPage> {
  final UserDao _userDao = UserDao();

  Future<void> _addUser() async {
    // 创建用户
    var user = UserModel(
      username: 'test_user',
      nickname: 'Test User',
      age: 18,
      isVip: false,
      hobbies: ['reading', 'gaming'],
      followingIds: [1, 2, 3],
      extra: {'score': 100},
    );
    
    // 插入数据库
    int userId = await _userDao.insert(user);
    print('插入成功,用户ID:$userId');
    
    // 查询用户
    UserModel? dbUser = await _userDao.queryOne(userId);
    print('查询结果:$dbUser');
    
    // 更新VIP状态
    await _userDao.updateVipStatus(userId, true);
    
    // 更新关注列表
    await _userDao.updateFollowingIds(userId, [4, 5, 6]);
    
    // 查询所有VIP用户
    List<UserModel> vipUsers = await _userDao.queryVipUsers();
    print('VIP用户数量:${vipUsers.length}');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('用户管理')),
      body: Center(
        child: ElevatedButton(
          onPressed: _addUser,
          child: Text('添加测试用户'),
        ),
      ),
    );
  }
}

VI. 数据库表结构

上述模型会自动生成如下表结构:

CREATE TABLE IF NOT EXISTS tb_user (
  user_id INTEGER PRIMARY KEY AUTOINCREMENT,
  username TEXT,
  nickname TEXT,
  avatar TEXT,
  age INTEGER,
  height REAL,
  is_vip INTEGER,
  birthday INTEGER,
  hobbies TEXT,  -- 列表类型将自动转换为JSON字符串
  following_ids TEXT, -- 列表类型将自动转换为JSON字符串
  extra TEXT -- 映射类型将自动转换为JSON字符串
)

关键特性:

  1. 支持的数据类型:

    • INTEGER:用于int类型
    • REAL:用于double类型
    • TEXT:用于String类型
    • INTEGER:用于bool类型(0/1)
  2. 复杂类型处理:

    • 列表和映射类型将自动转换为JSON字符串
    • 在读取时自动解析回原始类型
    • 不需要手动编写类型转换器
  3. 主键配置:

    • 使用 user_id 作为主键
    • 设置为自增
    • 通过 primaryKeyAndValue 方法指定

VII. 重要注意事项

  1. 数据库相关

    • 新字段必须在数据库升级时手动添加
    • 复杂类型会占用更多存储空间
    • 调试工具建议仅在调试模式下使用
    • FFI版本性能更好但需要额外配置
  2. 类型安全

    • 所有字段应为可空类型
    • JSON解析时进行类型检查
    • 数据库操作期间进行类型转换
  3. 性能优化

    • 避免存储大型复杂类型
    • 合理设计表结构和索引
    • 使用事务进行批量操作

VIII. 示例项目

完整的示例项目请参考:

以上内容提供了如何使用 json2dart_safe 插件进行JSON到Dart模型的转换,并结合数据库操作的完整示例。希望对你有所帮助!


更多关于Flutter JSON转Dart模型插件json2dart_safe的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter JSON转Dart模型插件json2dart_safe的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用json2dart_safe插件将JSON转换为Dart模型的详细步骤,包括相关的代码示例。

步骤 1: 添加依赖

首先,在你的pubspec.yaml文件中添加json2dart_safe依赖:

dependencies:
  flutter:
    sdk: flutter
  json2dart_safe: ^x.y.z  # 请替换为最新版本号

然后在项目根目录下运行flutter pub get来安装依赖。

步骤 2: 准备JSON数据

假设你有以下的JSON数据:

{
  "id": 1,
  "name": "John Doe",
  "email": "john.doe@example.com"
}

步骤 3: 使用json2dart_safe生成Dart模型

你可以在命令行中使用json2dart_safe工具来生成Dart模型。假设你的JSON数据保存在一个名为data.json的文件中,你可以运行以下命令:

flutter pub run json2dart_safe --input data.json --output models/user_model.dart

这个命令会根据data.json的内容生成一个名为user_model.dart的Dart文件,并将其保存到models目录下。生成的user_model.dart文件可能看起来像这样:

// user_model.dart
class UserModel {
  int? id;
  String? name;
  String? email;

  UserModel({this.id, this.name, this.email});

  UserModel.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    email = json['email'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['id'] = id;
    data['name'] = name;
    data['email'] = email;
    return data;
  }
}

步骤 4: 在Flutter项目中使用生成的模型

现在你可以在Flutter项目中使用这个生成的模型了。例如,你可以从一个API获取JSON数据,并将其解析为UserModel对象:

import 'package:flutter/material.dart';
import 'dart:convert';
import 'models/user_model.dart'; // 导入生成的模型文件

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('JSON to Dart Model'),
        ),
        body: Center(
          child: FutureBuilder<UserModel>(
            future: fetchUser(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                }
                UserModel user = snapshot.data!;
                return Text(
                  'Name: ${user.name}, Email: ${user.email}',
                );
              } else {
                return CircularProgressIndicator();
              }
            },
          ),
        ),
      ),
    );
  }

  Future<UserModel> fetchUser() async {
    // 模拟从API获取JSON数据
    final response = await http.get(Uri.parse('https://api.example.com/user/1'));

    if (response.statusCode == 200) {
      // 解析JSON数据为UserModel对象
      Map<String, dynamic> jsonData = jsonDecode(response.body);
      return UserModel.fromJson(jsonData);
    } else {
      throw Exception('Failed to load user');
    }
  }
}

请注意,上面的代码示例使用了http包来模拟从API获取数据。如果你还没有添加http包到你的项目中,可以在pubspec.yaml中添加它:

dependencies:
  http: ^0.13.3  # 请替换为最新版本号

然后运行flutter pub get来安装它。

这样,你就完成了使用json2dart_safe插件将JSON数据转换为Dart模型并在Flutter项目中使用它的整个过程。

回到顶部