Flutter JSON解析插件json_native的使用

Flutter JSON解析插件json_native的使用

如果您在Dart中处理JSON数据时遇到困难,并且json_serializable并不总是最佳选择,尤其是当JSON结构不明确或动态变化,或者您只需要提取少数几个值时,那么json_native插件可能会对您有所帮助。json_native插件旨在简化JSON解析过程,使代码更具可读性和可靠性。

概述

  • 当JSON结构不明确或动态变化时。
  • 当您只需要提取少数几个值,而创建一个完整的数据模型显得过于复杂时。
  • 当您处理json_serializable无法处理的复杂类型,例如联合类型时。

在这种情况下,您可能会退回到原始的jsonDecode方法,但这种方法也带来了一系列挑战。

使用jsonDecode的问题

考虑以下JSON字符串:

{
  "int": 1,
  "string": "string",
  "double": 1.1,
  "bool": true,
  "intList": [1, 2, 3],
  "stringList": ["a", "b", "c"],
  "mixedList": ["a", 1, false],
  "obj": { "key": "value" },
  "foo": { "bar": { "baz": true, "string": "string" } },
  "mixed": [{ "object": { "key": "value" } }]
}

通常,您会使用以下代码来解析这个JSON字符串:

final root = jsonDecode(jsonString) as Map<String, dynamic>;

final intValue = root['int'] as int;
final strValue = root['string'] as String?;
final doubleValue = root['double'] as double;
final intList = (root['intList'] as List).cast<int>();
final stringList = (root['stringList'] as List).cast<String>();
final mixedList = root['mixedList'] as List;
final obj = root['obj'] as Map<String, dynamic>;
final baz = root['foo']['bar']['baz'] as bool;
final value = root['mixed'][0]['object']['key'] as String;

虽然这种方法功能上是可行的,但它存在一些缺点:

  • 代码可读性差。
  • 容易出错。
  • 处理可选字段比较棘手。
  • 调试起来可能比较困难。

使用json_native的解决方案

json_native插件旨在通过更易读且不易出错的代码来简化这一过程。

以下是具体实现步骤:

import 'package:json_native/json_native.dart';

final JsonObject root = jsonDecodeCast(jsonString);
// Yes, JsonObject isn't a new type but an type alias!
print(root.runtimeType == Map<String, dynamic>);

// get would cast the type for you
final intValue = root.get<int>('int');

// Yes, nullable type is also supported
final strValue = root.get<String?>('string');

// Type inference would figure out the generic param
final double doubleValue = root.get('double');

// Get a strong typed list
final intList = root.getList<int>('intList');

// Again, type inference would save the generic parameter.
final List<String> stringList = root.getList('stringList');

// If generic parameter is not given, it falls back to dynamic, which can be omitted.
final mixedList = root.getList('mixedList');

// getObj returns JsonObject.
final obj = root.getObj('obj');

// You can nested a series of get into a dig.
final baz = root.dig<bool>(['foo', 'bar', 'baz']);

// dig also support mixed of list and object
final value = root.dig<String>(['mixed', 0, 'object', 'key']);

特点

  • 类型转换自动处理。
  • 支持可空类型。
  • 类型推断消除了显式泛型参数的需求。
  • 提供强类型的列表。
  • 允许通过dig进行嵌套对象和列表遍历。

完整示例代码

以下是一个完整的示例代码,展示了如何使用json_native插件解析JSON数据。

// ignore_for_file: unused_local_variable, avoid_dynamic_calls, avoid_print

import 'package:json_native/json_native.dart';

const jsonString = """
{
  "int": 1,
  "string": "string",
  "double": 1.1,
  "bool": true,
  "intList": [1, 2, 3],
  "stringList": ["a", "b", "c"],
  "obj": { "key": "value" },
  "foo": { "bar": { "baz": true, "string": "string" } },
  "mixed": [{ "object": { "key": "value" } }]
}
""";

void main() {
  vanilla();
  withJsonNative();
}

void vanilla() {
  final root = jsonDecode(jsonString) as Map<String, dynamic>;

  final intValue = root['int'] as int;
  final strValue = root['string'] as String;
  final doubleValue = root['double'] as double;
  final intList = (root['intList'] as List).cast<int>();
  final stringList = (root['stringList'] as List).cast<String>();
  final obj = root['obj'] as Map<String, dynamic>;
  final baz = root['foo']['bar']['baz'] as bool;
  final value = root['mixed'][0]['object']['key'] as String;
}

void withJsonNative() {
  final JsonObject root = jsonDecodeCast(jsonString);

  // Yes, JsonObject isn't a new type but an type alias!
  print(root.runtimeType == Map<String, dynamic>);

  // get would cast the type for you
  final intValue = root.get<int>('int');

  // Yes, nullable type is also supported
  final strValue = root.get<String?>('string');

  // Type inference would figure out the generic param
  final double doubleValue = root.get('double');

  // Get a strong typed list
  final intList = root.getList<int>('intList');

  // Again, type inference would save the generic parameter.
  final List<String> stringList = root.getList('stringList');

  // If generic parameter is not given, it falls back to dynamic, which can be omitted.
  final mixedList = root.getList('mixedList');

  // getObj returns JsonObject.
  final obj = root.getObj('obj');

  // You can nested a series of get into a dig.
  final baz = root.dig<bool>(['foo', 'bar', 'baz']);

  // dig also support mixed of list and object
  final value = root.dig<String>(['mixed', 0, 'object', 'key']);
}

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

1 回复

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


在Flutter中,json_native 是一个高效的 JSON 解析插件,它利用了 Dart 的原生扩展(FFI)来提高 JSON 解析的速度。以下是如何在 Flutter 项目中使用 json_native 插件的示例代码。

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  json_native: ^最新版本号  # 请替换为实际的最新版本号

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

2. 配置原生代码(iOS 和 Android)

由于 json_native 使用 FFI,你可能需要在 iOS 和 Android 项目中进行一些配置。但通常情况下,json_native 插件已经为你处理好了大部分配置。如果你遇到任何与原生代码相关的问题,可以查阅该插件的官方文档或 GitHub 仓库。

3. 使用 json_native 解析 JSON

下面是一个使用 json_native 解析 JSON 的示例代码:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('JSON Native Example'),
        ),
        body: Center(
          child: FutureBuilder<Map<String, dynamic>>(
            future: _fetchAndParseJson(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                } else {
                  Map<String, dynamic> data = snapshot.data!;
                  return Text('Name: ${data['name']}, Age: ${data['age']}');
                }
              } else {
                return CircularProgressIndicator();
              }
            },
          ),
        ),
      ),
    );
  }

  Future<Map<String, dynamic>> _fetchAndParseJson() async {
    // 假设这是从网络获取的 JSON 字符串
    String jsonString = '''
    {
      "name": "John Doe",
      "age": 30
    }
    ''';

    // 使用 json_native 解析 JSON
    JsonNative jsonNative = JsonNative();
    Map<String, dynamic> result = jsonNative.decode(jsonString);

    return result;
  }
}

4. 注意事项

  • 确保你已经正确配置了 FFI 所需的原生代码(尽管大多数情况下 json_native 插件已经为你处理了这些配置)。
  • json_native 的 API 可能与 Dart 内置的 jsonDecode 略有不同,但基本概念是相似的。你可以查阅 json_native 的文档以了解更多详细信息。
  • 由于 FFI 可能会引入一些复杂性,如果你只是进行简单的 JSON 解析,Dart 内置的 jsonDecode 可能是更简单、更直接的选择。然而,对于性能敏感的应用,json_native 可以提供显著的性能提升。

5. 性能比较

虽然这里没有直接的性能比较代码,但你可以通过基准测试来比较 json_native 和 Dart 内置的 jsonDecode 在你的具体用例中的性能。这通常涉及测量解析大量 JSON 数据所需的时间。

希望这个示例代码能帮助你开始在 Flutter 项目中使用 json_native 插件进行 JSON 解析!

回到顶部