Flutter JSON解析插件parse_json的使用

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

Flutter JSON解析插件 parse_json 的使用

parse_json 是一个用于在Flutter中进行类型安全的JSON反序列化的插件。它不需要代码生成或反射,而是通过构造函数的命名参数来匹配JSON键。它支持许多特性,如可选字段、嵌套类型、多态/继承、枚举和集合等。

安装

首先,你需要在你的项目中添加 parse_json 包:

对于Flutter项目:

flutter pub add parse_json

对于Dart项目:

dart pub add parse_json

然后,在你的Dart代码中导入这个包:

import 'package:parse_json/parse_json.dart';

基本用法

假设你有如下JSON数据:

{
  "myString": "exampleStr",
  "myDouble": 12.5
}

你可以定义一个类,并创建一个工厂方法来解析JSON数据:

import 'package:parse_json/parse_json.dart';

final class ExampleObject {
  final String myString;
  final double myDouble;

  const ExampleObject({
    required this.myString,
    required this.myDouble,
  });

  factory ExampleObject.fromJson(dynamic json) => 
    parse(
      ExampleObject.new, // 使用的构造函数
      json,
      // 注意:这里的键必须与构造函数的命名参数匹配
      {
        'myString': string,
        'myDouble': float,
      },
    );
}

成员变量名称可以不同

成员变量的名字不需要与JSON中的键名相同。你可以定义一个特殊的构造函数,其命名参数与JSON键匹配,并使用你喜欢的任何名称作为成员变量。例如:

import 'package:parse_json/parse_json.dart';

final class ExampleObject {
  final String name;
  final double originalHeight;
  double currentHeight;

  const ExampleObject.json({
    required String myString,
    required double myDouble,
  }) : name = myString,
       originalHeight = myDouble,
       currentHeight = myDouble;

  const ExampleObject(this.name, this.originalHeight, this.currentHeight);

  factory ExampleObject.fromJson(dynamic json) => 
    parse(
      ExampleObject.json, // 使用的构造函数
      json,
      {
        'myString': string,
        'myDouble': float,
      },
    );
}

复杂示例

如果你有更复杂的JSON结构,比如包含列表、嵌套对象或可选字段,你可以这样处理:

列表和嵌套对象

假设你有如下JSON数据:

{
  "myBoolList": [false, true, false],
  "myIntList": [12, 10, 5],
  "myFriend": {
    "myString": "friendStr",
    "myDouble": 10.5
  },
  "myOptionalFriend": ... another friend or this field could be omitted
  "friendList": [
    ... more friends
  ]
}

你可以定义一个类来解析这个JSON数据:

import 'package:parse_json/parse_json.dart';

final class SimpleObject {
  final String myString;
  final double myDouble;

  const SimpleObject({
    required this.myString,
    required this.myDouble,
  });

  factory SimpleObject.fromJson(dynamic json) => 
    parse(
      SimpleObject.new,
      json,
      {
        'myString': string,
        'myDouble': float,
      }
    );
}

final class ComplexExampleObject {
  final List<bool> myBoolList;
  final List<int> myIntList;
  final SimpleObject myFriend;
  final SimpleObject? myOptionalFriend;
  final List<SimpleObject> friendList;

  const ComplexExampleObject({
    required this.myBoolList,
    required this.myIntList,
    required this.myFriend,
    required this.friendList,
    this.myOptionalFriend,
  });

  factory ComplexExampleObject.fromJson(dynamic json) => 
    parse(
      ComplexExampleObject.new,
      json,
      {
        'myBoolList': boolean.list,
        'myIntList': integer.list,
        'myFriend': SimpleObject.fromJson.required,
        'myOptionalFriend': SimpleObject.fromJson.optional,
        'friendList': SimpleObject.fromJson.list,
      },
    );
}

枚举

如果JSON中有枚举值,你可以为枚举定义一个 fromJson 工厂方法:

enum ExampleEnum {
  a,
  b,
  c;

  factory ExampleEnum.fromJson(dynamic json) => switch (json) {
        'abbracaddabra' => ExampleEnum.a,
        'bye-bye' => ExampleEnum.b,
        'ciao' => ExampleEnum.c,
        _ => throw Exception('Unknown enum value')
      };
}

final class ObjectWithEnums {
  final ExampleEnum a;
  final ExampleEnum? b;
  final Map<String, List<ExampleEnum>>? c;

  const ObjectWithEnums({
    required this.a,
    this.b,
    this.c,
  });

  factory ObjectWithEnums.fromJson(dynamic json) =>
      parse(
        ObjectWithEnums.new, 
        json, 
        {
          'a': ExampleEnum.fromJson.required,
          'b': ExampleEnum.fromJson.optional,
          'c': ExampleEnum.fromJson.list.stringMap.optional,
        }
      );
}

默认值

你可以为某些字段提供默认值:

final class SimpleDefaults {
  final String myString;
  final double myDouble;
  final int myInt;
  final bool myBool;

  const SimpleDefaults({
    required this.myString,
    required this.myInt,
    required this.myDouble,
    required this.myBool,
  });

  factory SimpleDefaults.fromJson(dynamic json) =>
    parse(
      SimpleDefaults.new, 
      json, 
      {
        'myString': string,
        'myDouble': float.withDefault(12.5),
        'myInt': integer,
        'myBool': boolean.withDefault(true),
      },
    );
}

集合

对于集合(如列表和映射),你可以使用 .list, .map, .stringMap.intMap 方法:

import 'package:parse_json/parse_json.dart';

final class ExampleObject {
  final List<String> myStringList;
  final Map<String, double> myStringDoubleMap;

  const ExampleObject({
    required this.myStringList,
    required this.myStringDoubleMap,
  });

  factory ExampleObject.fromJson(dynamic json) => 
    parse(
      ExampleObject.new,
      json,
      {
        'myStringList': string.list,
        'myStringDoubleMap': float.stringMap,
      }
    );
}

继承和多态类型

对于继承或多态类型的基类,你需要使用 polymorphicParse 方法:

import 'package:parse_json/parse_json.dart';

final class BaseClass {
  static const polymorphicKey = 'type';
  
  final String myString;
  final double myDouble;

  const BaseClass({
    required this.myString,
    required this.myDouble,
  });

  factory BaseClass.fromJson(dynamic json) => 
    polymorphicParse(
      polymorphicKey,
      json,
      {
        SubClassA.polymorphicId: SubClassA.fromJson,
        SubClassB.polymorphicId: SubClassB.fromJson,
      },
      baseDefinition: DefinedType(BaseClass.new, {
        'myString': string,
        'myDouble': float,
    }));
}

final class SubClassA extends BaseClass {
  static const polymorphicId = 'A';

  final int myInt;

  const SubClassA({
    required super.myString,
    required super.myDouble,
    required this.myInt,
  });

  factory SubClassA.fromJson(dynamic json) => 
    parse(
      SubClassA.new,
      json,
      {
        'myString': string,
        'myDouble': float,
        'myInt': integer,
      },
    );
}

final class SubClassB extends BaseClass {
  static const polymorphicId = 'B';

  final ExampleObject myExampleObject;

  const SubClassB({
    required super.myString,
    required super.myDouble,
    required this.myExampleObject,
  });

  factory SubClassB.fromJson(dynamic json) => 
    parse(
      SubClassB.new,
      json,
      {
        'myString': string,
        'myDouble': float,
        'myExampleObject': ExampleObject.fromJson.required,
      },
    );
}

示例Demo

以下是一个完整的示例程序,展示了如何使用 parse_json 插件来解析简单的JSON数据:

import 'package:parse_json/parse_json.dart';

void main() {
  // 示例JSON数据
  final json = {
    "myString": "exampleStr",
    "myDouble": 12.5,
    "myBoolList": [false, true, false],
    "myIntList": [12, 10, 5],
    "myFriend": {
      "myString": "friendStr",
      "myDouble": 10.5
    },
    "friendList": [
      {"myString": "friend1", "myDouble": 1.1},
      {"myString": "friend2", "myDouble": 2.2}
    ]
  };

  // 解析JSON并创建对象
  final exampleObject = ComplexExampleObject.fromJson(json);

  print('My String: ${exampleObject.myFriend.myString}');
  print('My Double: ${exampleObject.myFriend.myDouble}');
  print('My Bool List: ${exampleObject.myBoolList}');
  print('My Int List: ${exampleObject.myIntList}');
  print('First Friend in List: ${exampleObject.friendList[0].myString}');
}

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

1 回复

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


在Flutter中,处理JSON数据是一个常见的需求。parse_json插件实际上并不是一个广泛认知的Flutter插件,用于JSON解析的插件通常是json_annotation,它配合Dart的内置JSON处理功能,可以非常方便地解析和序列化JSON数据。不过,假设你提到的parse_json是一个自定义的或者特定用途的插件,这里我将展示如何使用标准的Dart JSON解析方法,以及如何使用json_annotation插件来进行更复杂的JSON解析。

使用Dart内置JSON解析

Dart提供了内置的JSON解析和序列化功能,通过dart:convert库中的jsonDecodejsonEncode方法来实现。

示例代码:

import 'dart:convert';

void main() {
  // 示例JSON字符串
  String jsonString = '{"name": "John", "age": 30, "isStudent": false}';

  // 解析JSON字符串为Dart对象
  Map<String, dynamic> userMap = jsonDecode(jsonString);

  // 访问数据
  String name = userMap['name'];
  int age = userMap['age'];
  bool isStudent = userMap['isStudent'];

  print('Name: $name');
  print('Age: $age');
  print('Is Student: $isStudent');
}

使用json_annotation插件进行复杂JSON解析

对于更复杂的JSON结构,我们可以定义Dart类,并使用json_annotation插件来自动生成从JSON到Dart对象的转换代码。

步骤:

  1. 添加依赖: 在pubspec.yaml文件中添加json_annotation依赖。

    dependencies:
      flutter:
        sdk: flutter
      json_annotation: ^4.3.0  # 请检查最新版本号
    
  2. 创建数据模型: 定义一个Dart类,并使用jsonSerializable注解。

    import 'package:json_annotation/json_annotation.dart';
    
    part 'user.g.dart'; // 将生成的代码放在这个文件中
    
    [@JsonSerializable](/user/JsonSerializable)()
    class User {
      final String name;
      final int age;
      final bool isStudent;
    
      User({required this.name, required this.age, required this.isStudent});
    
      // 从JSON生成User对象
      factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
    
      // 将User对象转换为JSON
      Map<String, dynamic> toJson() => _$UserToJson(this);
    }
    
  3. 生成代码: 运行flutter pub run build_runner build命令来生成user.g.dart文件。

  4. 使用数据模型: 现在你可以使用这个数据模型来解析和序列化JSON数据。

    import 'dart:convert';
    import 'user.dart'; // 导入你定义的User类
    
    void main() {
      // 示例JSON字符串
      String jsonString = '{"name": "John", "age": 30, "isStudent": false}';
    
      // 解析JSON字符串为User对象
      User user = User.fromJson(jsonDecode(jsonString));
    
      // 访问数据
      print('Name: ${user.name}');
      print('Age: ${user.age}');
      print('Is Student: ${user.isStudent}');
    
      // 将User对象转换为JSON字符串
      String userJson = jsonEncode(user.toJson());
      print('User JSON: $userJson');
    }
    

以上代码展示了如何在Flutter中使用标准的Dart JSON解析方法以及json_annotation插件来处理JSON数据。如果你提到的parse_json插件有特定的用法或功能,建议查阅该插件的官方文档或源代码以获取准确的使用指南。

回到顶部