首页 教程 服务器/数据库 [Flutter]Json序列化json_serializable使用属性全介绍

[Flutter]Json序列化json_serializable使用属性全介绍

结合上一篇介绍[Flutter]Json和序列化数据,看浏览关注的人还是很多。这里出一篇详细介绍json_serializable的属性参数的解析说明。此文章根据目前最新版本json_serializable: ^6.9.0介绍 ,下面开始:

一、一般使用介绍

// json_serializable模型写法示意 import 'package:json_annotation/json_annotation.dart'; //当前文件名+.g.dart part 'device_model.g.dart'; //添加注解 @JsonSerializable() class DeviceTypeNetModel { final num? deviceType; final String? deviceTypeName; //自定义一些属性的某些设置 @JsonKey(name: 'num') final int? count; //构造函数 DeviceTypeNetModel(this.deviceType, this.deviceTypeName, this.count); //工厂构造函数fromJson(也可以不写,需要配置对应的设置) factory DeviceTypeNetModel.fromJson(Map<String, dynamic> json) => _$DeviceTypeNetModelFromJson(json); //转json (也可以不写,需要配置对应的设置) Map<String, dynamic> toJson() => _$DeviceTypeNetModelToJson(this); }

二、JsonKey参数解析

[Flutter]Json序列化json_serializable使用属性全介绍

defaultValue:Object?

  • 功能:指定字段的默认值。当 JSON 中没有该字段时,将使用 defaultValue 提供的值。
  • 用法:如果 JSON 数据中某个字段缺失,defaultValue 可以为其提供默认值,避免字段变为 null 或触发错误。

@JsonKey(defaultValue: 'Unknown') final String name;

如果 JSON 数据中没有 name 字段,默认值 Unknown 会被使用。

disallowNullValue:bool?

  • 功能:用于toJson的时候防止字段值为 null,如果字段的值为 null,会抛出 ArgumentError。
  • 用法:用于要求某个字段永远不能为 null,如果传入 null,则会抛出异常。

@JsonKey(disallowNullValue: true) final String name;

如果 name 字段为 null,在序列化时将抛出错误。

fromJson 和 toJson : Function?

  • 功能:用于指定自定义的序列化和反序列化函数。这对于复杂的数据类型或者需要特殊处理的字段特别有用。
  • 用法:可以通过 fromJson 来指定如何将 JSON 数据转换为 Dart 对象,toJson 用于指定如何将 Dart 对象转换为 JSON。

@JsonKey(fromJson: _fromJson, toJson: _toJson) final DateTime timestamp; static DateTime _fromJson(String timestamp) { return DateTime.parse(timestamp); } static String _toJson(DateTime timestamp) { return timestamp.toIso8601String(); }

这里,timestamp 字段会使用自定义的 fromJson 和 toJson 方法进行解析和序列化。

name: String?

  • 功能:用于指定字段在 JSON 中的键名。通常在 Dart 类字段名与 JSON 中的键名不匹配时使用。
  • 用法:如果 Dart 类中的字段名与 JSON 中的字段名不一致,可以使用 name 指定要使用的 JSON 键。

@JsonKey(name: 'full_name') final String name;

在上面的示例中,name 字段会被序列化为 full_name,而不是默认的 name。

includeFromJson 和 includeToJson : bool?

  • 功能:如果设置为 true,该字段将被忽略,在 toJson 和 fromJson 中都不会参与序列化和反序列化。不会影响模型基准构造函数的赋值使用。
  • 用法:用于那些不希望在 JSON 中进行序列化和反序列化的字段。

@JsonKey(includeFromJson: true,includeToJson: true) final String temporaryData;

这里,temporaryData 字段将不会出现在生成的 JSON 中,并且也不会参与 fromJson 过程。

includeIfNull:bool?

  • 功能:用于控制字段是否在 toJson 时包含 null 值。如果设置为 false,该字段即使为 null 也会被忽略。(默认从默认配置中获取即为true)
  • 用法:常用于希望在序列化时避免生成冗余的 null 字段。

@JsonKey(includeIfNull: false) final String? email;

如果 email 字段为 null,它将不会出现在生成的 JSON 中。

readValue: Object? Function(Map,Srting)?

  • 功能:用于转化接口返回的类型。(有局限性,建议使用fromJson和toJson替换)
  • 用法:常用于希望在接收使用的数据类型和接口返回的json中字段类型不一致的情况。

@JsonKey(readValue: NormalTool.transFromMill) final String timeMill; class NormalTool { static String transFromMill(Map p0, String p1) { return p0[p1].toString(); } }

//注意这里转化基本类型可以,但是如果是DateTime类型会出现不属于基本类型的转化toJson会被定义为String,进而影响fromJson的转化。

例如上述的如果转化为DateTime,得到的.g.dart的转化内容如下:

DeviceTypeNetModel _$DeviceTypeNetModelFromJson(Map<String, dynamic> json) => DeviceTypeNetModel( DateTime.parse(NormalTool.transFromMill(json, 'timeMill') as String), ); Map<String, dynamic> _$DeviceTypeNetModelToJson(DeviceTypeNetModel instance) => <String, dynamic>{ 'timeMill': instance.timeMill.toIso8601String(), };

required:bool?

  • 功能:表示该字段在 JSON 中是必须的,必须提供该字段的值。和构造函数标注属性必须有内容类似。
  • 用法:当你需要确保某个字段在序列化时不为 null 并且 JSON 中必须包含该字段时,可以使用此属性。

@JsonKey(required: true) final String name;

这意味着,name 字段在 JSON 中是必须存在的,否则解析时会抛出异常。

unknownEnumValue : Enum?

  • 功能:用于处理枚举类型的字段。当 JSON 数据包含一个未在 Dart 枚举中定义的值时,使用 unknownEnumValue 来指定默认值。
  • 用法:非常有用,尤其是在处理与外部 API 交互时,API 可能会传回新的、未在枚举中定义的值。

@JsonKey(unknownEnumValue: Gender.other) final Gender gender;

如果 JSON 中的 gender 字段值不是枚举中定义的 male、female,则默认使用 Gender.other。

三、JsonSerializable参数解析

[Flutter]Json序列化json_serializable使用属性全介绍

anyMap:bool?

  • 类型:bool,默认值是 false。
  • 描述:如果为 true,则会将 Map 的 fromJson 方法生成的参数类型从 Map 改为 Map。这可以用于处理一些动态类型的数据。

@JsonSerializable(anyMap: true) class User { final String name; User({required this.name}); }

checked: bool?

  • 类型:bool,默认值是 false。
  • 描述:如果为 true,则会将fromJson按照类型校验类型正确的反序列化,如果类型校验不通过则会抛出异常CheckedFromJsonException

@JsonSerializable(checked: true) class User { final String name; User({required this.name}); }

constructor: String?

  • 类型:String?,默认值是 null。
  • 描述:指定一个构造函数的名称。如果你的类有多个构造函数,或者需要通过特定的构造函数来创建对象,可以使用此参数。

@JsonSerializable(constructor: 'customConstructor') class User { final String name; User.customConstructor({required this.name}); }

在这个例子中,User 类会使用 customConstructor 来生成实例。

createFieldMap: bool?

  • 类型:bool,默认值是 false。
  • 描述:如果为 true,则会创建一个私有的方法_$ExampleJsonMeta 返回模型名称对应Json的key

@JsonSerializable(createFieldMap: true) class DeviceTypeNetModel { final num? deviceType; final String? deviceTypeName; @JsonKey(name: 'num') final int? count; final DeviceListCountNetModel model; DeviceTypeNetModel(this.deviceType, this.deviceTypeName, this.count, this.model); Map<String, String> fieldMap() => _$DeviceTypeNetModelFieldMap; } .g.dart 会多一个内部私有方法 const _$DeviceTypeNetModelFieldMap = <String, String>{ 'deviceType': 'deviceType', 'deviceTypeName': 'deviceTypeName', 'count': 'num', 'model': 'model', };

createJsonKeys: bool?

  • 类型:bool,默认值是 false。
  • 描述:同上createFieldMap,内部创建一个私有的_$ExampleJsonKeys,创建一个静态的字符常量定义,变量名为项目属性名,指向内容是Json的key。

@JsonSerializable(createJsonKeys: true) class DeviceTypeNetModel { final num? deviceType; final String? deviceTypeName; @JsonKey(name: 'num') final int? count; final DeviceListCountNetModel model; DeviceTypeNetModel(this.deviceType, this.deviceTypeName, this.count, this.model); } .g.dart 会多一个内部私有方法 abstract final class _$DeviceTypeNetModelJsonKeys { static const String deviceType = 'deviceType'; static const String deviceTypeName = 'deviceTypeName'; static const String count = 'num'; static const String model = 'model'; }

createFactory: bool?

  • 类型:bool,默认值是 true。
  • 描述:如果为 false,不会为该类生成 fromJson 工厂方法。可以通过手动定义 fromJson 工厂方法来控制反序列化过程。

@JsonSerializable(createFactory: false) class User { final String name; User({required this.name}); // 手动定义 fromJson 方法 static User fromJson(Map<String, dynamic> json) { return User(name: json['name']); } }

createToJson: bool?

  • 类型:bool,默认值是 true。
  • 描述:如果为 false,则不生成 toJson 方法。你可以手动定义自己的 toJson 方法,或者完全不需要序列化成 JSON。

@JsonSerializable(createToJson: false) class User { final String name; User({required this.name}); // 手动定义 toJson 方法 Map<String, dynamic> toJson() { return {'name': name}; }

disallowUnrecognizedKeys: bool?

  • 类型:bool,默认值是 false。
  • 描述:默认false,表示fromJson中的JSON有多余的字段忽略,如果设置为true,则JSON存在多余的key会抛出异常}UnrecognizedKeysException

explicitToJson: bool?

  • 类型:bool,默认值是 false。
  • 描述:如果为 true,则嵌套对象的 toJson 方法会被显式调用。默认情况下,json_serializable 会递归地将对象转化为 JSON,而不需要显式调用嵌套类的 toJson 方法。如果你希望强制嵌套对象也使用自己的 toJson,可以设置为 true。

@JsonSerializable(explicitToJson: true) class User { final String name; final Address address; User({required this.name, required this.address}); factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); Map<String, dynamic> toJson() => _$UserToJson(this); } @JsonSerializable() class Address { final String city; final String street; Address({required this.city, required this.street}); factory Address.fromJson(Map<String, dynamic> json) => _$AddressFromJson(json); Map<String, dynamic> toJson() => _$AddressToJson(this); }

在这个例子中,User 类会显式调用 Address 类的 toJson,而不依赖于 json_serializable 的递归自动处理。

fieldRename: FieldRename?

  • 类型:FieldRename,可以设置为 none(默认值),snake , kebab,pascal,screamingSnake。
  • 描述:指定字段名的转换规则,通常用于处理 Dart 中的驼峰命名和 JSON 中的下划线命名。
    • none:保留原字段名(默认值)。
    • snake:将字段名转换为蛇形命名(camelCase -> snake_case)。
    • kebab:将字段名转换为短横线命名(camelCase -> kebab-case)。
    • pascal: 将字段名转换为大驼峰命名(pascalCase -> PascalCase)。
    • screamingSnake: 将字段名转换为单词大写下划线连接 (screamingSnakeCase -> SCREAMING_SNAKE_CASE)。

@JsonSerializable(fieldRename: FieldRename.snake) class User { final String firstName; final String lastName; User({required this.firstName, required this.lastName}); }

在这个例子中,firstName 会被转换为 first_name,lastName 会被转换为 last_name。

ignoreUnannotated: bool?

  • 类型:bool,默认值是 false。
  • 描述:如果为 true,则 json_serializable 会忽略没有被 @JsonKey 标注的字段。这对于类中有很多字段,但只希望某些字段进行序列化时非常有用。

@JsonSerializable(ignoreUnannotated: true) class User { final String name; @JsonKey(name: 'age_in_years') final int age; User({required this.name, required this.age}); }

如果你设置了 ignoreUnannotated: true,name 字段不会被包含在生成的 toJson 和 fromJson 方法中,只有 age 字段会被序列化。

includeIfNull: bool?

  • 类型:bool,默认值是 true。
  • 描述:针对toJson,如果值是null的时候是否写入导出的JSON中。

converters: List?

  • 类型:List
  • 描述:自定义解释器,内部的fromJson和toJson都将自定义实现,取消自动生成的转化。

@JsonSerializable(converters: [MyJsonConverter()]) class Example { //也可以单独指定某一个属性做特殊自定义解释 //@MyJsonConverter() final DateTime property; Example(this.property); } class MyJsonConverter extends JsonConverter<DateTime, String> { const MyJsonConverter(); @override DateTime fromJson(String json) { return DateTime.parse(json); } @override String toJson(DateTime object) { return ''; } }

genericArgumentFactories: bool?

  • 类型:bool,默认值是 false。
  • 描述:针对范型,下面第四块会做介绍使用。

createPerFieldToJson: bool?

  • 类型:bool,默认值是 false。
  • 描述:会创建一个私有方法 _$ExamplePerFieldToJson 。这个抽象类将为每个属性包含一个静态函数,从而提供了一种仅对该属性而不是整个对象进行设置的方法。

@JsonSerializable(createPerFieldToJson: true) class DeviceTypeNetModel { final num? deviceType; final String? deviceTypeName; @JsonKey(name: 'num') final int? count; final DeviceListCountNetModel model; DeviceTypeNetModel(this.deviceType, this.deviceTypeName, this.count, this.model); } .g.dart 会多一个内部私有方法 // ignore: unused_element abstract class _$DeviceTypeNetModelPerFieldToJson { // ignore: unused_element static Object? deviceType(num? instance) => instance; // ignore: unused_element static Object? deviceTypeName(String? instance) => instance; // ignore: unused_element static Object? count(int? instance) => instance; // ignore: unused_element static Object? model(DeviceListCountNetModel instance) => instance; }

四、范型T

json serializable 在大概两年前发布的v3.5.0版本开始支持泛型,只需要在 @JsonSerializable() 注解中设置genericArgumentFactories为 true,同时需要对 fromJson 和 toJson 方法进行调整,即可支持泛型解析,如下所示:

@JsonSerializable(genericArgumentFactories: true) class Response<T> { int status; T value; factory Response.fromJson(Map<String, dynamic>json, T Function(dynamic json) fromJsonT) => _$ResponseFromJson<T>(json, fromJsonT); Map<String, dynamic> toJson(Object? Function(T value) toJsonT) => _$ResponseToJson<T>(this, toJsonT); } 得到的.g.dart 文件内容如下: Response<T> _$ResponseFromJson<T>( Map<String, dynamic> json, T Function(Object? json) fromJsonT, ) => Response<T>( (json['status'] as num).toInt(), fromJsonT(json['value']), ); Map<String, dynamic> _$ResponseToJson<T>( Response<T> instance, Object? Function(T value) toJsonT, ) => <String, dynamic>{ 'status': instance.status, 'value': toJsonT(instance.value), };

适用于一些固定结构,可以预处理一部分业务,其中某个参数根据业务变化在外部处理业务的场景(接口响应很经典)。

五、枚举

enum StatusCode { @JsonValue(200) success, @JsonValue(301) movedPermanently, @JsonValue(302) found, @JsonValue(500) internalServerError, } @JsonSerializable() class BackModel { StatusCode code; BackModel(this.code); factory BackModel.fromJson(Map<String, dynamic> json) => _$BackModelFromJson(json); Map<String, dynamic> toJson() => _$BackModelToJson(this); } 得到的.g.dart 文件内容如下: BackModel _$BackModelFromJson(Map<String, dynamic> json) => BackModel( $enumDecode(_$StatusCodeEnumMap, json['code']) ); Map<String, dynamic> _$BackModelToJson(BackModel instance) => <String, dynamic>{ 'code': _$StatusCodeEnumMap[instance.code]!, }; const _$StatusCodeEnumMap = { StatusCode.success: 200, StatusCode.movedPermanently: 301, StatusCode.found: 302, StatusCode.internalServerError: 500, };

或者

@JsonEnum(valueField: 'code') enum StatusCodeEnhanced { success(200), movedPermanently(301), found(302), internalServerError(500); const StatusCodeEnhanced(this.code); final int code; } @JsonSerializable() class BackModel { StatusCodeEnhanced status; BackModel(this.status); factory BackModel.fromJson(Map<String, dynamic> json) => _$BackModelFromJson(json); Map<String, dynamic> toJson() => _$BackModelToJson(this); } 得到的.g.dart 文件内容如下: BackModel _$BackModelFromJson(Map<String, dynamic> json) => BackModel( $enumDecode(_$StatusCodeEnhancedEnumMap, json['status']), ); Map<String, dynamic> _$BackModelToJson(BackModel instance) => <String, dynamic>{ 'status': _$StatusCodeEnhancedEnumMap[instance.status]!, }; const _$StatusCodeEnhancedEnumMap = { StatusCodeEnhanced.success: 200, StatusCodeEnhanced.movedPermanently: 301, StatusCodeEnhanced.found: 302, StatusCodeEnhanced.internalServerError: 500, };

枚举记得使用注解unknownEnumValue,以便后续代码健壮性 @JsonKey(unknownEnumValue: Gender.other)

评论(0)条

提示:请勿发布广告垃圾评论,否则封号处理!!

    猜你喜欢
    【MySQL】用户管理

    【MySQL】用户管理

     服务器/数据库  2个月前  2.18k

    我们推荐使用普通用户对数据的访问。而root作为管理员可以对普通用户对应的权限进行设置和管理。如给张三和李四这样的普通用户权限设定后。就只能操作给你权限的库了。

    Cursor Rules 让开发效率变成10倍速

    Cursor Rules 让开发效率变成10倍速

     服务器/数据库  2个月前  1.23k

    在AI与编程的交汇点上,awesome-cursorrules项目犹如一座灯塔,指引着开发者们驶向更高效、更智能的编程未来。无论你是经验丰富的老手,还是刚入行的新人,这个项目都能为你的编程之旅增添一抹亮色。这些规则文件就像是你私人定制的AI助手,能够根据你的项目需求和个人偏好,精确地调教AI的行为。突然间,你会发现AI不仅能理解Next.js的最佳实践,还能自动应用TypeScript的类型检查,甚至主动提供Tailwind CSS的类名建议。探索新的应用场景,推动AI辅助编程的边界。

    探索Django 5: 从零开始,打造你的第一个Web应用

    探索Django 5: 从零开始,打造你的第一个Web应用

     服务器/数据库  2个月前  1.16k

    Django 是一个开放源代码的 Web 应用程序框架,由 Python 写成。它遵循 MVT(Model-View-Template)的设计模式,旨在帮助开发者高效地构建复杂且功能丰富的 Web 应用程序。随着每个版本的升级,Django 不断演变,提供更多功能和改进,让开发变得更加便捷。《Django 5 Web应用开发实战》集Django架站基础、项目实践、开发经验于一体,是一本从零基础到精通Django Web企业级开发技术的实战指南《Django 5 Web应用开发实战》内容以。

    MySQL 的mysql_secure_installation安全脚本执行过程介绍

    MySQL 的mysql_secure_installation安全脚本执行过程介绍

     服务器/数据库  2个月前  1.09k

    mysql_secure_installation 是 MySQL 提供的一个安全脚本,用于提高数据库服务器的安全性

    【MySQL基础篇】概述及SQL指令:DDL及DML

    【MySQL基础篇】概述及SQL指令:DDL及DML

     服务器/数据库  2个月前  489

    数据库是长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。数据库不仅仅是数据的简单堆积,而是遵循一定的规则和模式进行组织和管理的。数据库中的数据可以包括文本、数字、图像、音频等各种类型的信息。

    Redis中的哨兵(Sentinel)

    Redis中的哨兵(Sentinel)

     服务器/数据库  2个月前  315

    ​ 上篇文章我们讲述了Redis中的主从复制(Redis分布式系统中的主从复制-CSDN博客),本篇文章针对主从复制中的问题引出Redis中的哨兵,希望本篇文章会对你有所帮助。