Flutter JSON 序列化 - 不生成 *.g.dart 文件

Gan*_*ani 10 json flutter

我是 flutter 的新手,目标是序列化包含其他较小对象的复杂 JSON 对象。

使用json_serializable: ^2.0.0pubspec.yaml文件看起来像这样。

dependencies:
  intl: ^0.15.7
  json_annotation: ^2.0.0
  built_value: ^6.7.1
  flutter:
    sdk: flutter

dev_dependencies:
  build_runner: ^1.0.0
  json_serializable: ^2.0.0
  built_value_generator: ^6.7.1
  flutter_test:
    sdk: flutter
Run Code Online (Sandbox Code Playgroud)

这个user.dart样子

import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable(nullable: false)
class User {
  final String firstName;
  final String lastName;
  final DateTime dateOfBirth;
  User({this.firstName, this.lastName, this.dateOfBirth});
  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试flutter pub run build_runner build过文件 user.g.dart 没有被创建,我面临着这个问题。

我还添加了build.yaml以下代码的文件

targets:
  $default:
    builders:
      built_value_generator|built_value:
        generate_for:
          - model/*.dart
      json_serializable|json_serializable:
        generate_for:
          - model/*.dart
Run Code Online (Sandbox Code Playgroud)

谁能让我知道我在这里缺少什么。谢谢

小智 15

构造函数的参数不应该是可选的

User({this.firstName, this.lastName, this.dateOfBirth});
Run Code Online (Sandbox Code Playgroud)

他们应该是强制性的:

User(this.firstName, this.lastName, this.dateOfBirth);
Run Code Online (Sandbox Code Playgroud)

还有那部分

'user.g.dart';
Run Code Online (Sandbox Code Playgroud)

应该匹配大写用户类:

part 'User.g.dart';
Run Code Online (Sandbox Code Playgroud)


Bak*_*ker 10

清单

  • 你的类文件在 /lib 或 /bin 下
    • 可以是那些下的子目录
    • json_serializable 不会在每个目录中搜索要生成的文件。
  • 为 json_annotation 添加了导入:
    • import 'package:json_annotation/json_annotation.dart';
  • partimport语句 之后添加了一个指令
    • 您的part文件以您的类文件名(而不是类名本身)命名,并g添加了
    • 例如,对于CacheItem...
    • cache-item.dart 类文件名...
    • part 'cache-item.g.dart';得到相应的part指令。
    • part指令不是以您的实际类命名,而是以类文件名命名。
  • 您已@JsonSerializable()在班级名称上方添加
  • 你已经为你的类创建了一个默认的构造函数
    • 它可以是空的,具有可选的命名参数或位置参数。
    • 只要您的类字段可访问(通过构造函数或公共 setter 和 getter),json_serializable 就可以处理它。(即不只有 _private 属性和一个空的构造函数)
  • 您已经编写了存根方法:
    • factory <Class>.fromJson(json) => _$ClassFromJson(json);
    • toJson() => _$ClassToJson(this)
    • 存根方法是私有的(以_下划线开头)
    • $tub 方法有 $
    • 存根方法有适当的案例(即Pascal Case
    • 存根factory供应(Map<String,dynamic> json)作为参数
    • 存根toJson()返回Map<String,dynamic>

全部完成后,尝试从项目根目录运行生成器...

在颤振中:

flutter pub run build_runner build

在纯 Dart 中:

pub run build_runner build

常见错误

Bad state: Unexpected diagnostics:

在运行 build_runner 时看到此输出可能是 flutter 的问题,并且json_annotation取决于不兼容的analyzer. 这发生在 3.5 之前的json_serializable版本中,需要将分析器dependency_override 设置为 0.39.14 或 0.39.17。

你的第一步应该是从 pub.dev尝试最新版本的json_serilizable ,显然没有这个依赖问题

如果您无法升级 json_serializable,您可以尝试将覆盖行放在下面dev_dependences

dev_dependencies:
  build_runner: ^1.9.0
  flutter_test:
    sdk: flutter
  json_serializable: 3.3.0
  test: ^1.14.3

dependency_overrides:
  analyzer: '0.39.14'
Run Code Online (Sandbox Code Playgroud)

笔记

子类/父类

如果您的类是父类的子类,并且您只想序列化子类的字段/属性,则只能注释子类。将自动找到父类字段并将其包含在为子类生成的类文件中。

如果你希望能够序列化/反序列化两个父母和孩子分开,继续前进,与注释底座/父类@JsonSerializable为好。

例如文件名 account.dart

import 'package:json_annotation/json_annotation.dart';

part 'account.g.dart';

class AccountBase {
  int created;
  String username;
  String password;
}

@JsonSerializable()
class Account extends AccountBase {
  int id;

  Account();

  factory Account.fromJson(Map<String,dynamic> json) => _$AccountFromJson(json);
  Map<String,dynamic> toJson() => _$AccountToJson(this);
}
Run Code Online (Sandbox Code Playgroud)

产生:

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'account.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

Account _$AccountFromJson(Map<String, dynamic> json) {
  return Account()
    ..created = json['created'] as int
    ..username = json['username'] as String
    ..password = json['password'] as String
    ..id = json['id'] as int;
}

Map<String, dynamic> _$AccountToJson(Account instance) => <String, dynamic>{
      'created': instance.created,
      'username': instance.username,
      'password': instance.password,
      'id': instance.id,
    };
Run Code Online (Sandbox Code Playgroud)

参考和文档

例子

import 'package:json_annotation/json_annotation.dart';

part 'cache-item.g.dart';

@JsonSerializable()
class CacheItem {
  int created;
  String keywords;
  String response;

  CacheItem(this.created, this.keywords, this.response);

  factory CacheItem.fromJson(Map<String,dynamic> json) => _$CacheItemFromJson(json);
  Map<String,dynamic> toJson() => _$CacheItemToJson(this);
}
Run Code Online (Sandbox Code Playgroud)

输出

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'cache-item.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

CacheItem _$CacheItemFromJson(Map<String, dynamic> json) {
  return CacheItem(
    json['created'] as int,
    json['keywords'] as String,
    json['response'] as String,
  );
}

Map<String, dynamic> _$CacheItemToJson(CacheItem instance) => <String, dynamic>{
      'created': instance.created,
      'keywords': instance.keywords,
      'response': instance.response,
    };

Run Code Online (Sandbox Code Playgroud)

示例构造函数变体

这个例子与上面相同,只是构造函数缺少一些字段并且具有response可选字段。

没关系。

在实例化对象后,生成器将只使用公共(隐式)setter 来分配值。

import 'package:json_annotation/json_annotation.dart';

part 'cache-item.g.dart';

@JsonSerializable()
class CacheItem {
  int created;
  String keywords;
  String response;

  CacheItem({this.response});

  factory CacheItem.fromJson(Map<String,dynamic> json) => _$CacheItemFromJson(json);
  Map<String,dynamic> toJson() => _$CacheItemToJson(this);
}
Run Code Online (Sandbox Code Playgroud)

输出

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'cache-item.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

CacheItem _$CacheItemFromJson(Map<String, dynamic> json) {
  return CacheItem(
    response: json['response'] as String,
  )
    ..created = json['created'] as int
    ..keywords = json['keywords'] as String;
}

Map<String, dynamic> _$CacheItemToJson(CacheItem instance) => <String, dynamic>{
      'created': instance.created,
      'keywords': instance.keywords,
      'response': instance.response,
    };

Run Code Online (Sandbox Code Playgroud)


Sam*_*Sam 8

尝试跑步

>flutter packages pub run build_runner build --delete-conflicting-outputs
Run Code Online (Sandbox Code Playgroud)


小智 5

如果您尝试通过运行命令来生成 .g 文件flutter packages pub run build_runner build,但没有得到所需的结果,那么只需尝试:

  1. flutter clean

  2. 'flutter pub 缓存修复'

  3. flutter packages pub run build_runner build --delete-conflicting-outputs

  4. 删除所有 gradle 临时文件

  5. 然后运行flutter pub get

  6. flutter packages pub run build_runner build