Flutter JSON解析插件simple_json的使用

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

Flutter JSON解析插件simple_json的使用

simple_json 是一种动态方式,在给定类型的情况下,通过构建时生成器从和到JSON进行转换。

注意:忽略警告和标签,这些表明此包与Flutter和其他SDK不兼容。这是因为此生成器包使用了 dart:mirrors 库,该库在那些SDK中不受支持。在这种情况下,一切都会正常工作,因为此包应仅作为构建时生成器添加。此包应 dev_dependencies 中添加才能正确工作。支持的包 simple_json_mapper 也需要包含,但应在 dependencies 中作为常规依赖项。

如何使用?

  1. 当执行 build_runner build 命令时,会生成一个 mapper.g.dart 文件。查看生成文件示例高级示例

  2. 这个生成的文件包含必要的代码(序列化和反序列化逻辑)以实现从和到JSON的映射。

  3. 这些对象映射器在初始化函数中注册到JSON映射器中。

  4. 初始化函数应该是您的 main.dart 文件中的第一行代码。

  5. 在运行时,所有映射器都通过上述 init 方法注册,并且可以通过传递到 serialize<T>deserialize<T> 泛型方法的类类型参数来查找。

为什么使用?

  • 简单
  • 没有每个可序列化文件的杂乱 .g.dart 文件(单个根级文件包含所有生成的代码)
  • 动态序列化和反序列化,无需直接使用实际类型即可保持类型安全。即 JsonMapper.serialize(account) 对比 account.toJson()(account 不需要任何逻辑,且在实际序列化过程中不会被直接使用)
  • 模型文件保持干净(没有额外的生成代码),并且不关心序列化逻辑(单一职责原则)
  • 无需指定自定义对象和可迭代类型的强制转换
  • 没有针对整个类型的冗余反射,且没有代码检查/分析问题

动态序列化和反序列化允许创建很棒的类型安全API。一个简单的例子是在Flutter中创建一个简单的存储服务。

class StorageService implements IStorageService {
  const StorageService(this.preferences);
  final SharedPreferences preferences;

  @override
  Future<T> get<T>({T Function() defaultFn, bool private = false}) async {
    return getWithKey(T.toString(), defaultFn: defaultFn, private: private);
  }

  @override
  Future<T> getWithKey<T>(String key, {T Function() defaultFn, bool private = false}) async {
    return JsonMapper.deserialize<T>(await getProvider(private).getString(key)) ?? defaultFn();
  }

  @override
  Future<bool> set<T>(T value, [bool private = false]) {
    return setWithKey(T.toString(), value, private);
  }

  @override
  Future<bool> setWithKey<T>(String key, T value, [bool private = false]) {
    return getProvider(private).setString(key, JsonMapper.serialize(value));
  }

  IStorageProvider getProvider(bool private) {
    return private && !AppUtils.isWeb
        ? SecureStorage()
        : SharedPreferencesStorage(preferences);
  }
}

使用 simple_json,此 StorageService 具有一个简单的泛型类型安全API,可以在存储之前将模型类序列化为字符串,使其非常简单且无样板代码。

快速开始

pubspec.yaml注意simple_json 必须添加到 dev_dependencies

dependencies:
  simple_json_mapper: ^2.2.0

dev_dependencies:
  simple_json: ^2.2.0
  build_runner: ^1.10.0

设置

main.dart

// 生成的文件。可以添加到.gitignore
import 'mapper.g.dart' as mapper;

void main() {
  mapper.init();
  ...
}

使用

模型

import 'package:simple_json_mapper/simple_json_mapper.dart';

// 需要的注解/装饰器,以使模型参与JSON设置。等效于 [JsonObject]
[@JObj](/user/JObj)()
class Account {
  const Account({
    this.type,
    this.name,
    this.number,
    this.amount,
    this.transactionCount,
    this.isActive,
    this.product,
    this.localText,
  });
  // 指定枚举序列化的类型(基于索引或值)。等效于 [JsonEnumProperty]
  // SerializationType.Index: Savings = 0, Checking = 1
  // SerializationType.Value: Savings = 'Savings', Checking = 'Checking'
  // 枚举字段可以使用 [EnumValue] 注解以提供自定义值。
  @JEnumProp(serializationType: SerializationType.Index)
  final AccountType type;
  final String name;
  final String number;
  final double amount;

  @JsonProperty(name: 'tranCount', defaultValue: 11)
  final int transactionCount;

  final bool isActive;

  // 等效于 [JsonProperty]
  @JProp(ignore: true)
  final String localText;

  final Product product;
}

@JsonObject()
class Product {
  const Product({this.name, this.expiry, this.sizes, this.tests});
  final String name;
  final DateTime expiry;
  final List<int> sizes;
  final List<Test> tests;
}

// 链接模型不需要注解,但建议使用。
class Test {
  const Test({this.name});
  final String name;
}

enum AccountType {
  // 覆盖序列化枚举值
  @EnumValue(value: 25)
  Savings,
  @EnumValue(value: 10)
  Checking
}

序列化

  final product = Product(
    name: 'Test',
    expiry: DateTime.now(),
    sizes: [10, 20, 40],
    tests: [
      Test(name: 'hello'),
      Test(name: 'blah'),
    ],
  );
  final account = Account(
    type: AccountType.Checking,
    name: 'Test',
    number: 'xxx12414',
    amount: 100.50,
    transactionCount: 10,
    isActive: true,
    product: product,
    localText: 'ignored text',
  );
  final accountJson = JsonMapper.serialize(account);

反序列化

  final account = JsonMapper.deserialize<Account>(accountJson);

转换器

  // 将所有反序列化的字符串转换为小写,所有序列化的字符串转换为大写。
  JsonMapper.registerConverter(
    JsonConverter<String, String>.fromFunction(
      fromJson: (value) => value.toLowerCase(),
      toJson: (value) => value.toUpperCase(),
    ),
  );

  // 转换器用于将所有日期时间字符串值转换为由给定类定义的特殊格式。
  JsonMapper.registerConverter(SpecialDateTimeConverter());

自定义JsonMapper

  // 自定义映射器,具有自己的转换器集。对于封装特殊、临时序列化很有用,例如SQLite
  final customMapper = CustomJsonMapper(
    converters: [
      // 转换器用于将所有布尔值从布尔值转换为整数,并在序列化时从整数转换回布尔值。
      JsonConverter<int, bool>.fromFunction(
        fromJson: (value) => value == 1 ? true : false,
        toJson: (value) => value ? 1 : 0,
      ),
    ],
  );
  // 注意这里使用了 [customerMapper]。
  print(customMapper.serialize(account));

生成映射文件

构建

# dart
pub get
pub run build_runner build
# flutter
flutter pub get
flutter packages pub run build_runner build

监视

# dart
pub get
pub run build_runner watch
# flutter
flutter pub get
flutter packages pub run build_runner watch

完整示例

以下是一个完整的示例,展示了如何使用 simple_json 进行序列化和反序列化。

import 'package:simple_json_mapper/simple_json_mapper.dart';
import 'mapper.g.dart' as mapper;

void main() {
  mapper.init();
  // 确保在运行此示例之前运行以下命令
  // pub get
  // pub run build_runner build
  final jsonStr = JsonMapper.serialize(Test(name: 'Blah'));
  print('Serialized JSON:');
  print(jsonStr);
  print('\nDeserialized and re-serialized JSON:');
  print(JsonMapper.serialize(JsonMapper.deserialize<Test>(jsonStr)));
}

[@JObj](/user/JObj)()
class Test {
  const Test({required this.name});
  final String name;
}

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

1 回复

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


在Flutter开发中,simple_json 是一个轻量级的 JSON 解析插件。尽管 Flutter 社区中更常用的是 dart:convert 库来处理 JSON 数据,但如果你特定地想要了解如何使用 simple_json,这里有一个简单的示例来展示其基本用法。

首先,确保你的 pubspec.yaml 文件中已经添加了 simple_json 依赖:

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

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

以下是一个使用 simple_json 解析 JSON 数据的示例:

示例 JSON 数据

假设你有以下 JSON 数据:

{
  "name": "Flutter",
  "version": "3.0.0",
  "features": [
    "Hot Reload",
    "Cross-Platform",
    "Material Design"
  ]
}

Flutter 代码示例

  1. 导入 simple_json 包。
  2. 使用 simple_json 解析 JSON 数据。
import 'package:flutter/material.dart';
import 'package:simple_json/simple_json.dart'; // 导入simple_json包

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('simple_json 示例'),
        ),
        body: Center(
          child: JsonParsingExample(),
        ),
      ),
    );
  }
}

class JsonParsingExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 示例JSON字符串
    String jsonString = '''
    {
      "name": "Flutter",
      "version": "3.0.0",
      "features": [
        "Hot Reload",
        "Cross-Platform",
        "Material Design"
      ]
    }
    ''';

    // 使用simple_json解析JSON字符串
    Json jsonData = Json.parse(jsonString);

    // 提取数据
    String name = jsonData['name'];
    String version = jsonData['version'];
    List<String> features = jsonData['features'].cast<String>();

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text('Name: $name'),
        Text('Version: $version'),
        Text('Features:'),
        Wrap(
          children: features.map((feature) => Text(feature)).toList(),
        ),
      ],
    );
  }
}

注意事项

  1. simple_json vs dart:convert: 尽管 simple_json 提供了另一种方式来解析 JSON,但 dart:convert 通常是首选方法,因为它是 Flutter SDK 的一部分,不需要额外的依赖,且性能通常更优。如果你没有特定的理由使用 simple_json,建议使用 dart:convert

  2. 错误处理: 在实际应用中,处理 JSON 解析错误是很重要的。例如,你可以使用 try-catch 块来捕获可能的异常。

  3. 性能: 对于大型 JSON 数据集,确保测试性能,以确保所选的解析方法满足应用需求。

使用 dart:convert 的示例

为了对比,这里是一个使用 dart:convert 的简单示例:

import 'dart:convert';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('dart:convert 示例'),
        ),
        body: Center(
          child: JsonParsingExample(),
        ),
      ),
    );
  }
}

class JsonParsingExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 示例JSON字符串
    String jsonString = '''
    {
      "name": "Flutter",
      "version": "3.0.0",
      "features": [
        "Hot Reload",
        "Cross-Platform",
        "Material Design"
      ]
    }
    ''';

    // 使用dart:convert解析JSON字符串
    Map<String, dynamic> jsonData = jsonDecode(jsonString);

    // 提取数据
    String name = jsonData['name'];
    String version = jsonData['version'];
    List<String> features = List<String>.from(jsonData['features']);

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text('Name: $name'),
        Text('Version: $version'),
        Text('Features:'),
        Wrap(
          children: features.map((feature) => Text(feature)).toList(),
        ),
      ],
    );
  }
}

希望这能帮助你理解如何在 Flutter 中使用 simple_json 进行 JSON 解析。如果你有其他问题或需要进一步的帮助,请随时提问!

回到顶部