Flutter快速JSON解析插件fast_json的使用

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

Flutter快速JSON解析插件fast_json的使用

介绍

fast_json 是一个用于Flutter项目的JSON解析插件,提供了多种JSON解析器,包括经典解析器、带有大数支持的经典解析器、带有JavaScript支持的经典解析器以及基于事件的解析器。这些解析器在性能和内存消耗方面进行了优化,适合处理大规模数据。

版本

当前版本为 0.1.12

解析器类型

  • 经典解析器:比Dart SDK稍慢,但具有更好的错误报告系统。
  • 带有大数支持的经典解析器:不受整数大小限制。
  • 带有JavaScript支持的经典解析器:在浏览器中解析速度较慢,在非浏览器环境中较快,未针对数字解析进行优化。
  • 基于事件的解析器(Parser-handler):同步解析器,不存储解析结果,而是调用事件处理器,适用于过滤读取数据。
  • 基于事件的选择器解析器(Parser-selector):基于Parser-handler实现,简化了数据选择。

示例代码

使用Parser-selector解析JSON数据
import 'package:fast_json/fast_json_selector.dart' as parser;
import 'package:fast_json/fast_json_selector.dart' show JsonSelectorEvent;

void main(List<String> args) {
  // 显示层级结构
  void select(JsonSelectorEvent event) {
    print('Level: ${event.levels.length}: ${event.levels.join(' ')}');
    print('Index: ${event.index}');
  }

  parser.parse(_data, select: select);

  // 查找来自特定城市的用户
  final cities = {'McKenziehaven', 'Wisokyburgh'};
  final users = <User>[];
  final level = '{} data [] 0 {}'.split(' ').length;
  void select(JsonSelectorEvent event) {
    if (event.levels.length == level) {
      final map = event.lastValue as Map;
      if (cities.contains(map['address']['city'])) {
        final user = User.fromJson(map);
        users.add(user);
      }
      // 释放内存
      event.lastValue = null;
    }
  }

  parser.parse(_data, select: select);
  print(users.join(', '));

  // 根据索引选择用户并终止选择
  final selectedUsers = <User>[];
  void selectByIndex(JsonSelectorEvent event) {
    final levels = event.levels;
    if (levels.length == level) {
      final index = event.index;
      if (index >= 2 && index <= 3) {
        final map = event.lastValue as Map;
        final user = User.fromJson(map);
        selectedUsers.add(user);
      }
      // 释放内存
      event.lastValue = null;
      if (selectedUsers.length == 2) {
        throw const _TerminateException();
      }
    }
  }

  try {
    parser.parse(_data, select: selectByIndex);
  } on _TerminateException {
    //
  }

  print(selectedUsers.join(', '));

  // 选择所有网站
  final websites = <String>[];
  void selectWebsites(JsonSelectorEvent event) {
    if (event.levels.length == level) {
      final map = event.lastValue as Map;
      final website = map['website'] as String;
      websites.add(website);
      // 释放内存
      event.lastValue = null;
    }
  }

  parser.parse(_data, select: selectWebsites);
  print(websites.join(', '));

  // 选择所有公司
  final companies = <Company>[];
  void selectCompanies(JsonSelectorEvent event) {
    if (event.levels.length == level) {
      final map = event.lastValue as Map;
      final company = Company.fromJson(map['company'] as Map);
      companies.add(company);
      // 释放内存
      event.lastValue = null;
    }
  }

  parser.parse(_data, select: selectCompanies);
  print(companies.join(', '));

  // 选择来自South Elvis的用户的公司
  final specificCompanies = <Company>[];
  void selectSpecificCompanies(JsonSelectorEvent event) {
    if (event.levels.length == level) {
      final map = event.lastValue as Map;
      if (map['address']['city'] == 'South Elvis') {
        final company = Company.fromJson(map['company'] as Map);
        specificCompanies.add(company);
      }
      // 释放内存
      event.lastValue = null;
    }
  }

  parser.parse(_data, select: selectSpecificCompanies);
  print(specificCompanies.join(', '));
}

const _data = '''
{
   "success":true,
   "data":[
      {
         "id":1,
         "name":"Leanne Graham",
         "username":"Bret",
         "email":"Sincere@april.biz",
         "address":{
            "street":"Kulas Light",
            "suite":"Apt. 556",
            "city":"Gwenborough",
            "zipcode":"92998-3874",
            "geo":{
               "lat":"-37.3159",
               "lng":"81.1496"
            }
         },
         "phone":"1-770-736-8031 x56442",
         "website":"hildegard.org",
         "company":{
            "name":"Romaguera-Crona",
            "catchPhrase":"Multi-layered client-server neural-net",
            "bs":"harness real-time e-markets"
         }
      },
      {
         "id":2,
         "name":"Ervin Howell",
         "username":"Antonette",
         "email":"Shanna@melissa.tv",
         "address":{
            "street":"Victor Plains",
            "suite":"Suite 879",
            "city":"Wisokyburgh",
            "zipcode":"90566-7771",
            "geo":{
               "lat":"-43.9509",
               "lng":"-34.4618"
            }
         },
         "phone":"010-692-6593 x09125",
         "website":"anastasia.net",
         "company":{
            "name":"Deckow-Crist",
            "catchPhrase":"Proactive didactic contingency",
            "bs":"synergize scalable supply-chains"
         }
      },
      {
         "id":3,
         "name":"Clementine Bauch",
         "username":"Samantha",
         "email":"Nathan@yesenia.net",
         "address":{
            "street":"Douglas Extension",
            "suite":"Suite 847",
            "city":"McKenziehaven",
            "zipcode":"59590-4157",
            "geo":{
               "lat":"-68.6102",
               "lng":"-47.0653"
            }
         },
         "phone":"1-463-123-4447",
         "website":"ramiro.info",
         "company":{
            "name":"Romaguera-Jacobson",
            "catchPhrase":"Face to face bifurcated interface",
            "bs":"e-enable strategic applications"
         }
      },
      {
         "id":4,
         "name":"Patricia Lebsack",
         "username":"Karianne",
         "email":"Julianne.OConner@kory.org",
         "address":{
            "street":"Hoeger Mall",
            "suite":"Apt. 692",
            "city":"South Elvis",
            "zipcode":"53919-4257",
            "geo":{
               "lat":"29.4572",
               "lng":"-164.2990"
            }
         },
         "phone":"493-170-9623 x156",
         "website":"kale.biz",
         "company":{
            "name":"Robel-Corkery",
            "catchPhrase":"Multi-tiered zero tolerance productivity",
            "bs":"transition cutting-edge web services"
         }
      },
      {
         "id":5,
         "name":"Chelsey Dietrich",
         "username":"Kamren",
         "email":"Lucio_Hettinger@annie.ca",
         "address":{
            "street":"Skiles Walks",
            "suite":"Suite 351",
            "city":"Roscoeview",
            "zipcode":"33263",
            "geo":{
               "lat":"-31.8129",
               "lng":"62.5342"
            }
         },
         "phone":"(254)954-1289",
         "website":"demarco.info",
         "company":{
            "name":"Keebler LLC",
            "catchPhrase":"User-centric fault-tolerant solution",
            "bs":"revolutionize end-to-end systems"
         }
      }
   ]
}''';

class Company {
  final String name;

  Company({required this.name});

  [@override](/user/override)
  String toString() {
    return name;
  }

  static Company fromJson(Map json) {
    return Company(
      name: json['name'] as String,
    );
  }
}

class User {
  final String city;
  final int id;
  final String name;

  User({required this.city, required this.id, required this.name});

  [@override](/user/override)
  String toString() {
    return '$id:$name from $city';
  }

  static User fromJson(Map json) {
    return User(
      city: json['address']['city'] as String,
      id: json['id'] as int,
      name: json['name'] as String,
    );
  }
}

class _TerminateException {
  const _TerminateException();
}
使用Parser-handler过滤JSON数据
import 'package:fast_json/fast_json_handler.dart' as parser;
import 'package:fast_json/fast_json_handler.dart' show JsonHandlerEvent, JsonParserHandler;

/// 过滤JSON数据而不将解析结果加载到内存中的示例
void main(List<String> args) {
  List buffer = [];
  dynamic lastValue;
  final keys = <String>[];
  var path = '';
  // 搜索条件
  final cities = {'McKenziehaven', 'Wisokyburgh'};
  var isSatisfies = false;
  var level = 0;

  void handle(JsonHandlerEvent event, dynamic value) {
    switch (event) {
      case JsonHandlerEvent.beginArray:
        buffer.add([]);
        break;
      case JsonHandlerEvent.beginObject:
        level++;
        buffer.add(<String, dynamic>{});
        break;
      case JsonHandlerEvent.endArray:
        lastValue = buffer.removeLast();
        break;
      case JsonHandlerEvent.endObject:
        level--;
        lastValue = buffer.removeLast();
        break;
      case JsonHandlerEvent.element:
        if (level > 0) {
          buffer.last.add(lastValue);
        } else if (isSatisfies) {
          buffer.last.add(lastValue);
        }
        break;
      case JsonHandlerEvent.beginKey:
        keys.add(value as String);
        path = keys.join('.');
        break;
      case JsonHandlerEvent.endKey:
        buffer.last[value] = lastValue;
        if (path == 'address.city') {
          isSatisfies = cities.contains(lastValue);
        }
        keys.removeLast();
        path = keys.join('.');
        break;
      case JsonHandlerEvent.value:
        // 处理不允许在此处出现的值
        lastValue = value;
        break;
    }
  }

  final handler = _JsonParserHandler(handle);
  parser.parse(_data, handler);
  final users = (lastValue as List).cast<Map<String, dynamic>>();
  print('搜索条件: 城市 ${cities.join(', ')}');
  print('找到 ${users.length} 个用户');
  for (final user in users) {
    print('${user['name']} 来自 ${user['address']['city']}');
  }
}

const _data = '''
[
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
      "name": "Romaguera-Crona",
      "catchPhrase": "Multi-layered client-server neural-net",
      "bs": "harness real-time e-markets"
    }
  },
  {
    "id": 2,
    "name": "Ervin Howell",
    "username": "Antonette",
    "email": "Shanna@melissa.tv",
    "address": {
      "street": "Victor Plains",
      "suite": "Suite 879",
      "city": "Wisokyburgh",
      "zipcode": "90566-7771",
      "geo": {
        "lat": "-43.9509",
        "lng": "-34.4618"
      }
    },
    "phone": "010-692-6593 x09125",
    "website": "anastasia.net",
    "company": {
      "name": "Deckow-Crist",
      "catchPhrase": "Proactive didactic contingency",
      "bs": "synergize scalable supply-chains"
    }
  },
  {
    "id": 3,
    "name": "Clementine Bauch",
    "username": "Samantha",
    "email": "Nathan@yesenia.net",
    "address": {
      "street": "Douglas Extension",
      "suite": "Suite 847",
      "city": "McKenziehaven",
      "zipcode": "59590-4157",
      "geo": {
        "lat": "-68.6102",
        "lng": "-47.0653"
      }
    },
    "phone": "1-463-123-4447",
    "website": "ramiro.info",
    "company": {
      "name": "Romaguera-Jacobson",
      "catchPhrase": "Face to face bifurcated interface",
      "bs": "e-enable strategic applications"
    }
  },
  {
    "id": 4,
    "name": "Patricia Lebsack",
    "username": "Karianne",
    "email": "Julianne.OConner@kory.org",
    "address": {
      "street": "Hoeger Mall",
      "suite": "Apt. 692",
      "city": "South Elvis",
      "zipcode": "53919-4257",
      "geo": {
        "lat": "29.4572",
        "lng": "-164.2990"
      }
    },
    "phone": "493-170-9623 x156",
    "website": "kale.biz",
    "company": {
      "name": "Robel-Corkery",
      "catchPhrase": "Multi-tiered zero tolerance productivity",
      "bs": "transition cutting-edge web services"
    }
  },
  {
    "id": 5,
    "name": "Chelsey Dietrich",
    "username": "Kamren",
    "email": "Lucio_Hettinger@annie.ca",
    "address": {
      "street": "Skiles Walks",
      "suite": "Suite 351",
      "city": "Roscoeview",
      "zipcode": "33263",
      "geo": {
        "lat": "-31.8129",
        "lng": "62.5342"
      }
    },
    "phone": "(254)954-1289",
    "website": "demarco.info",
    "company": {
      "name": "Keebler LLC",
      "catchPhrase": "User-centric fault-tolerant solution",
      "bs": "revolutionize end-to-end systems"
    }
  }
]''';

class _JsonParserHandler extends JsonParserHandler {
  final void Function(JsonHandlerEvent event, dynamic value) _handler;

  _JsonParserHandler(this._handler);

  [@override](/user/override)
  void handle(JsonHandlerEvent event, dynamic value) => _handler(event, value);
}

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

1 回复

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


当然,fast_json 是一个在 Flutter 中用于快速解析 JSON 数据的插件。以下是如何在 Flutter 项目中使用 fast_json 插件的示例代码。

步骤 1: 添加依赖

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

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

运行 flutter pub get 来获取依赖。

步骤 2: 创建数据模型

假设你有一个 JSON 数据结构如下:

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

你可以创建一个 Dart 数据模型类来表示这个 JSON 结构:

class User {
  int id;
  String name;
  String email;

  User({required this.id, required this.name, required this.email});

  // 从 Map 转换为 User 对象
  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'] as int,
      name: json['name'] as String,
      email: json['email'] as String,
    );
  }

  // 将 User 对象转换为 Map
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'email': email,
    };
  }
}

步骤 3: 使用 fast_json 解析 JSON

在 Flutter 应用中使用 fast_json 来解析 JSON 数据。以下是一个示例:

import 'package:flutter/material.dart';
import 'package:fast_json/fast_json.dart';
import 'dart:convert'; // 用于 jsonDecode

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

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

class UserDataWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 示例 JSON 数据
    String jsonString = '''
    {
      "id": 1,
      "name": "John Doe",
      "email": "john.doe@example.com"
    }
    ''';

    // 使用 jsonDecode 将 JSON 字符串转换为 Map
    Map<String, dynamic> jsonMap = jsonDecode(jsonString);

    // 使用 fast_json 解析 Map 为 User 对象
    var fastJsonParser = FastJsonParser();
    User user = fastJsonParser.parse(jsonMap, User.fromJson);

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text('ID: ${user.id}'),
        Text('Name: ${user.name}'),
        Text('Email: ${user.email}'),
      ],
    );
  }
}

注意事项

  1. FastJsonParserparse 方法接受两个参数:一个是 JSON 数据(可以是 MapList),另一个是一个函数,该函数将 MapList 转换为你的数据模型。
  2. fast_json 插件的使用方式与其他 JSON 解析库(如 json_serializable)略有不同,但它提供了一种简洁的解析方法。

希望这个示例代码能帮助你理解如何在 Flutter 中使用 fast_json 插件进行 JSON 解析。

回到顶部