Flutter数据编码解码插件conduit_codable的使用

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

Flutter数据编码解码插件conduit_codable的使用

简介

conduit_codable 是一个用于在Dart中对动态数据进行编码和解码的库。它允许你将JSON数据轻松地转换为Dart对象,并且可以处理复杂的嵌套结构、类型转换以及文档引用。

基本用法

定义数据类

数据类需要继承 Coding 类,并实现 decodeencode 方法。

import 'package:conduit_codable/conduit_codable.dart';

class Person extends Coding {
  String name;

  @override
  void decode(KeyedArchive object) {
    super.decode(object);
    name = object.decode("name");   
  }

  @override
  void encode(KeyedArchive object) {
    object.encode("name", name);
  }
}

从JSON读取数据

你可以从JSON字符串中读取数据并将其转换为Dart对象。

import 'dart:convert';
import 'package:conduit_codable/conduit_codable.dart';

void main() {
  final jsonString = '{"name": "Alice"}';
  final json = jsonDecode(jsonString);
  final archive = KeyedArchive.unarchive(json);
  final person = Person()..decode(archive);

  print(person.name); // 输出: Alice
}

将数据写入JSON

你也可以将Dart对象转换为JSON字符串。

import 'dart:convert';
import 'package:conduit_codable/conduit_codable.dart';

void main() {
  final person = Person()..name = "Bob";
  final archive = KeyedArchive.archive(person);
  final jsonString = jsonEncode(archive);

  print(jsonString); // 输出: {"name":"Bob"}
}

处理嵌套对象

Coding 对象可以编码或解码其他 Coding 对象,包括列表和映射中的 Coding 对象。你需要提供一个闭包来实例化被解码的 Coding 对象。

import 'package:conduit_codable/conduit_codable.dart';

class Team extends Coding {
  List<Person> members;
  Person manager;

  @override
  void decode(KeyedArchive object) {
    super.decode(object);
    members = object.decodeObjects("members", () => Person());
    manager = object.decodeObject("manager", () => Person());
  }

  @override
  void encode(KeyedArchive object) {
    object.encodeObject("manager", manager);
    object.encodeObjects("members", members);
  }
}

动态类型转换

对于具有原始类型参数(例如 List<String>Map<String, int>)的类型,在解码时可能会遇到问题。你可以通过重写 castMap 方法来进行类型转换。你需要导入 package:codable/cast.dart 并使用 cast 前缀。

import 'package:conduit_codable/conduit_codable.dart';
import 'package:codable/cast.dart' as cast;

class Container extends Coding {  
  List<String> things;

  @override
  Map<String, cast.Cast<dynamic>> get castMap => {
    "things": cast.List(cast.String)
  };

  @override
  void decode(KeyedArchive object) {
    super.decode(object);
    things = object.decode("things");
  }

  @override
  void encode(KeyedArchive object) {
    object.encode("things", things);
  }
}

文档引用

Coding 对象可以在文档中多次引用而不会重复其结构。对象通过 $ref 键进行引用。

{
  "components": {
    "thing": {
      "name": "The Thing"
    }    
  },
  "data": {
    "$ref": "#/components/thing"
  }
}

在上述JSON中,data 的解码值继承了 /components/thing 的所有属性:

{
  "$ref": "#/components/thing",
  "name": "The Thing"
}

你可以在内存中的数据结构中创建引用:

final person = Person()..referenceURI = Uri(path: "/teams/engineering/manager");

上述 person 编码为:

{
  "$ref": "#/teams/engineering/manager"
}

你还可以处理循环引用。

有关更多详细信息,请参阅 JSON Schema$ref 关键字的规范。

示例代码

以下是一个完整的示例,展示了如何使用 conduit_codable 进行数据编码和解码。

import 'dart:convert';
import 'package:conduit_codable/conduit_codable.dart';
import 'package:codable/cast.dart' as cast;

class Person extends Coding {
  String name;

  @override
  void decode(KeyedArchive object) {
    super.decode(object);
    name = object.decode("name");   
  }

  @override
  void encode(KeyedArchive object) {
    object.encode("name", name);
  }
}

class Team extends Coding {
  List<Person> members;
  Person manager;

  @override
  void decode(KeyedArchive object) {
    super.decode(object);
    members = object.decodeObjects("members", () => Person());
    manager = object.decodeObject("manager", () => Person());
  }

  @override
  void encode(KeyedArchive object) {
    object.encodeObject("manager", manager);
    object.encodeObjects("members", members);
  }
}

class Container extends Coding {  
  List<String> things;

  @override
  Map<String, cast.Cast<dynamic>> get castMap => {
    "things": cast.List(cast.String)
  };

  @override
  void decode(KeyedArchive object) {
    super.decode(object);
    things = object.decode("things");
  }

  @override
  void encode(KeyedArchive object) {
    object.encode("things", things);
  }
}

void main() {
  // 从JSON读取数据
  final jsonString = '{"name": "Alice"}';
  final json = jsonDecode(jsonString);
  final archive = KeyedArchive.unarchive(json);
  final person = Person()..decode(archive);
  print(person.name); // 输出: Alice

  // 将数据写入JSON
  final person2 = Person()..name = "Bob";
  final archive2 = KeyedArchive.archive(person2);
  final jsonString2 = jsonEncode(archive2);
  print(jsonString2); // 输出: {"name":"Bob"}

  // 处理嵌套对象
  final teamJson = '''
  {
    "manager": {"name": "Charlie"},
    "members": [{"name": "David"}, {"name": "Eve"}]
  }
  ''';
  final teamJsonObj = jsonDecode(teamJson);
  final teamArchive = KeyedArchive.unarchive(teamJsonObj);
  final team = Team()..decode(teamArchive);
  print(team.manager.name); // 输出: Charlie
  print(team.members.map((p) => p.name)); // 输出: [David, Eve]

  // 动态类型转换
  final containerJson = '{"things": ["one", "two", "three"]}';
  final containerJsonObj = jsonDecode(containerJson);
  final containerArchive = KeyedArchive.unarchive(containerJsonObj);
  final container = Container()..decode(containerArchive);
  print(container.things); // 输出: [one, two, three]

  // 文档引用
  final refJson = '''
  {
    "components": {
      "thing": {
        "name": "The Thing"
      }    
    },
    "data": {
      "\$ref": "#/components/thing"
    }
  }
  ''';
  final refJsonObj = jsonDecode(refJson);
  final refArchive = KeyedArchive.unarchive(refJsonObj);
  final data = refArchive.decode("data") as KeyedArchive;
  final thing = Person()..decode(data);
  print(thing.name); // 输出: The Thing
}

希望这些示例能帮助你更好地理解和使用 conduit_codable 插件。如果你有任何问题或需要进一步的帮助,请随时提问!


更多关于Flutter数据编码解码插件conduit_codable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据编码解码插件conduit_codable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用conduit_codable插件进行数据编码和解码的示例。conduit_codable是一个用于在Dart和Flutter中轻松进行JSON编码和解码的库。

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

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

然后运行flutter pub get来获取依赖。

接下来,我们将创建一个简单的数据模型,并使用conduit_codable对其进行编码和解码。

  1. 创建数据模型
import 'package:conduit_codable/conduit_codable.dart';

part 'user_model.g.dart';

@JsonSerializable()
class User {
  final String name;
  final int age;

  User({required this.name, required this.age});

  // 从JSON解码时调用的构造函数
  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);

  // 编码为JSON时调用的方法
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

注意:@JsonSerializable()注解告诉conduit_codable这个类需要生成JSON序列化代码。part 'user_model.g.dart';指定生成代码的文件名。

  1. 生成序列化代码

在命令行中运行以下命令来生成序列化代码:

flutter pub run build_runner build

这将在你的项目目录中生成一个user_model.g.dart文件,其中包含_$UserFromJson_$UserToJson方法的实现。

  1. 使用数据模型进行编码和解码
void main() {
  // 创建一个User对象
  User user = User(name: 'Alice', age: 30);

  // 将User对象编码为JSON
  Map<String, dynamic> userJson = user.toJson();
  print('Encoded JSON: $userJson');

  // 将JSON解码为User对象
  String jsonString = '{"name": "Bob", "age": 25}';
  Map<String, dynamic> jsonMap = jsonDecode(jsonString);
  User decodedUser = User.fromJson(jsonMap);
  print('Decoded User: ${decodedUser.name}, ${decodedUser.age}');
}

在这个示例中,我们首先创建了一个User对象,然后将其编码为JSON。接着,我们将一个JSON字符串解码为一个User对象。

这个示例展示了如何使用conduit_codable插件在Flutter中进行数据编码和解码。通过注解和代码生成,conduit_codable使得这一过程变得简单且高效。

回到顶部