Flutter深度选择插件deep_pick的使用

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

Flutter深度选择插件deep_pick的使用

deep_pick 是一个用于简化手动JSON解析的Dart包,它提供了一种类型安全的API来处理JSON数据。以下是关于如何在Flutter项目中使用deep_pick插件的详细介绍。

添加依赖

首先,在您的pubspec.yaml文件中添加deep_pick作为依赖:

dependencies:
  deep_pick: ^1.0.0

然后运行以下命令以安装该包:

$ dart pub add deep_pick

使用示例

示例代码

下面是一个完整的示例,展示了如何使用deep_pick从JSON响应中解析值。我们将创建一个名为Shoe的数据类,并展示如何从JSON结构中提取信息并映射到这个类。

定义数据类

class Shoe {
  const Shoe({
    required this.id,
    required this.name,
    this.manufacturer,
    required this.tags,
    required this.price,
  });

  factory Shoe.fromPick(RequiredPick pick) {
    final newApi = pick.fromContext('newApi').asBoolOrFalse();
    final pricePick = pick('price');
    return Shoe(
      id: pick('id').asStringOrThrow(),
      name: pick('name').asStringOrThrow(),
      manufacturer: newApi
          ? pick('manufacturer').asStringOrThrow()
          : pick('manufacturer').asStringOrNull(),
      tags: pick('tags').asListOrEmpty((it) => it.asStringOrThrow()),
      price: () {
        if (pricePick.isAbsent) return 'Not for sale';
        return pricePick.asStringOrNull() ?? 'Price available soon';
      }(),
    );
  }

  final String id;
  final String name;
  final String? manufacturer;
  final List<String> tags;
  final String price;

  @override
  String toString() {
    return 'Shoe{id: $id, name: "$name", price: "$price", tags: $tags}';
  }
}

解析JSON

接下来是主函数,展示了如何使用deep_pick来解析JSON数据:

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

const String rawJson = '''
{
  "shoes": [
     { 
       "id": "421",
       "name": "Nike Zoom Fly 3",
       "manufacturer": "nike",
       "tags": ["nike", "JustDoIt"]
     },
     { 
       "id": "532",
       "name": "adidas Ultraboost",
       "manufacturer": "adidas",
       "tags": ["adidas", "ImpossibleIsNothing"],
       "price": null
     }
  ]
}
''';

Future<void> main() async {
  final json = jsonDecode(rawJson);

  // 深度选择嵌套值
  final firstTag = pick(json, 'shoes', 1, 'tags', 0).asStringOrThrow();
  print(firstTag); // 输出: adidas

  // 获取可能为null的值
  final manufacturer = pick(json, 'shoes', 0, 'manufacturer').asStringOrNull();
  print(manufacturer); // 输出: nike

  // 将字符串转换为不同类型的值
  final id = pick(json, 'shoes', 0, 'id');
  print(id.asIntOrNull()); // 输出: 421
  print(id.asDoubleOrNull()); // 输出: 421.0
  print(id.asStringOrNull()); // 输出: "421"

  // 解析列表
  final tags = pick(json, 'shoes', 0, 'tags')
      .asListOrEmpty((it) => it.asStringOrThrow());
  print(tags); // 输出: [nike, JustDoIt]

  // 解析映射
  final shoe = pick(json, 'shoes', 0).required().asMapOrThrow();
  print(shoe); // 输出: {id: 421, name: Nike Zoom Fly 3, tags: [nike, JustDoIt]}

  // 映射对象到Dart对象
  final firstShoe = pick(json, 'shoes', 0).letOrNull((p) => Shoe.fromPick(p));
  print(firstShoe);
  // 输出: Shoe{id: 421, name: "Nike Zoom Fly 3", price: "Price available soon", tags: [nike, JustDoIt]}

  // 处理不存在的值
  final thirdShoe = pick(json, 'shoes', 2).letOrNull((p) => Shoe.fromPick(p));
  print(thirdShoe); // 输出: null

  // 解析整个列表
  final shoes = pick(json, 'shoes').asListOrEmpty((p) => Shoe.fromPick(p));
  print(shoes);
  // 输出: [
  //   Shoe{id: 421, name: "Nike Zoom Fly 3", price: "Price available soon", tags: [nike, JustDoIt]},
  //   Shoe{id: 532, name: "adidas Ultraboost", price: "Not for sale", tags: [adidas, ImpossibleIsNothing]}
  // ]

  // 访问超出范围的值
  final puma = pick(json, 'shoes', 1);
  print(puma.isAbsent); // 输出: true
  print(puma.value); // 输出: null

  // 加载来自API的数据
  final stats = await getStats();
  print(stats.requests);
}

Future<CounterApiStats> getStats() async {
  final response = await http.get(Uri.parse('https://api.countapi.xyz/stats'));
  final json = jsonDecode(response.body);

  // 解析单个字段
  final int? requests = pick(json, 'requests').asIntOrNull();
  final int keys_created = pick(json, 'keys_created').asIntOrThrow();
  final int? keys_updated = pick(json, 'keys_updated').asIntOrNull();
  final String? version = pick(json, 'version').asStringOrNull();
  print(
    'requests $requests, keys_created $keys_created, '
    'keys_updated: $keys_updated, version: "$version"',
  );

  // 解析完整对象
  final CounterApiStats stats = CounterApiStats.fromPick(pick(json).required());

  // 解析列表
  final List<CounterApiStats> multipleStats = pick(json, 'items')
      .asListOrEmpty((pick) => CounterApiStats.fromPick(pick));
  print(multipleStats); // 总是输出 [], 因为countapi没有items

  return stats;
}

class CounterApiStats {
  const CounterApiStats({
    required this.requests,
    required this.keys_created,
    required this.keys_updated,
    this.version,
  });

  final int requests;
  final int keys_created;
  final int keys_updated;
  final String? version;

  factory CounterApiStats.fromPick(RequiredPick pick) {
    return CounterApiStats(
      requests: pick('requests').asIntOrThrow(),
      keys_created: pick('keys_created').asIntOrThrow(),
      keys_updated: pick('keys_updated').asIntOrThrow(),
      version: pick('version').asStringOrNull(),
    );
  }
}

通过以上代码,您可以了解如何使用deep_pick插件进行JSON解析,包括如何处理嵌套值、不同类型之间的转换、解析列表和映射对象等。希望这些示例能帮助您更好地理解和使用deep_pick


更多关于Flutter深度选择插件deep_pick的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter深度选择插件deep_pick的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,deep_pick 是一个在 Flutter 中用于深度选择(Deep Linking)和数据解析的插件。通过它,你可以很方便地解析从 URL 传递的复杂数据。以下是一个如何使用 deep_pick 插件的基本示例代码案例。

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  deep_pick: ^x.y.z  # 请使用最新版本号

2. 导入插件

在你的 Dart 文件中导入 deep_pick

import 'package:deep_pick/deep_pick.dart';

3. 配置路由

你需要配置路由以处理深度链接。这通常使用 flutter_navigator 或类似的库,但 deep_pick 允许你轻松解析从 URL 中提取的数据。

4. 解析 URL 数据

假设你有一个 URL 如下:

https://example.com/deeplink?user={id:123,name:JohnDoe}&post={id:456,title:HelloFlutter}

你可以使用 deep_pick 来解析这个 URL 的数据:

import 'package:flutter/material.dart';
import 'package:deep_pick/deep_pick.dart';
import 'package:url_launcher/url_launcher.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Deep Linking Example'),
        ),
        body: Center(
          child: DeepLinkExample(),
        ),
      ),
    );
  }
}

class DeepLinkExample extends StatefulWidget {
  @override
  _DeepLinkExampleState createState() => _DeepLinkExampleState();
}

class _DeepLinkExampleState extends State<DeepLinkExample> {
  Map<String, dynamic> parsedData = {};

  @override
  void initState() {
    super.initState();
    // 模拟从 URL 获取的数据(通常这数据会从应用启动参数中获取)
    String url = "https://example.com/deeplink?user={id:123,name:JohnDoe}&post={id:456,title:HelloFlutter}";
    _parseDeepLink(url);
  }

  void _parseDeepLink(String url) async {
    try {
      // 使用 deep_pick 解析 URL
      Map<String, dynamic> deepLinkData = await DeepPick.parse(url);
      setState(() {
        parsedData = deepLinkData;
      });
      print("Parsed Data: $parsedData");
    } catch (e) {
      print("Error parsing deep link: $e");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text("Parsed User Data:"),
        if (parsedData.containsKey('user'))
          Text("ID: ${parsedData['user']['id']}, Name: ${parsedData['user']['name']}")
        else
          Text("No user data parsed"),
        Text("Parsed Post Data:"),
        if (parsedData.containsKey('post'))
          Text("ID: ${parsedData['post']['id']}, Title: ${parsedData['post']['title']}")
        else
          Text("No post data parsed"),
      ],
    );
  }
}

注意事项

  1. 实际应用中:URL 通常不会在代码中硬编码,而是从应用启动参数中读取。例如,你可以使用 window.defaultRouteNamegetInitialLink 等方法获取启动时的 URL。
  2. 安全性:解析来自 URL 的数据时要小心,确保进行必要的验证和清理,以防止安全问题。
  3. 实际数据格式:URL 编码可能因不同需求而有所不同,请确保数据格式和编码方式与 deep_pick 的解析能力相匹配。

通过这个示例,你可以看到如何使用 deep_pick 插件解析复杂的 URL 数据,并将其应用在你的 Flutter 应用中。

回到顶部