はじめに
FlutterでJsonを扱うならおそらくほとんどの人が使っているjson_serializableですが、
開発で扱う上でこういうのできないんだろうか?と疑問に思い、調べたことを紹介していこうと思います。
ネタが増えたら随時更新していきたいと思います。
インストール
flutter pub add json_annotation
flutter pub add --dev build_runner
flutter pub add --dev json_serializable
Jsonのキーの名前を変えたい
対象のフィールドに@JsonKey(name: 'xxxx')
をつけると、キーを変更できます。
import 'package:json_annotation/json_annotation.dart';
part 'author.g.dart';
@JsonSerializable()
class Author {
@JsonKey(name: 'author_id')
final String authorId;
final String name;
Author({
required this.authorId,
required this.name,
});
factory Author.fromJson(Map<String, dynamic> json) => _$AuthorFromJson(json);
Map<String, dynamic> toJson() => _$AuthorToJson(this);
}
final json = {
'author_id': "0001",
'name': "Tanaka Taro",
};
フィールドすべてを一括で変更したい場合はクラス名の上に、@JsonSerializable(fieldRename: FieldRename.snake)
を付けます。
import 'package:json_annotation/json_annotation.dart';
part 'author.g.dart';
@JsonSerializable(fieldRename: FieldRename.snake)
class Author {
final String authorId;
final String name;
Author({
required this.authorId,
required this.name,
});
factory Author.fromJson(Map<String, dynamic> json) => _$AuthorFromJson(json);
Map<String, dynamic> toJson() => _$AuthorToJson(this);
}
nullの場合はJsonに出力しないようにする
nullの場合にJsonに出力したくない場合は@JsonKey(includeIfNull: false)
をフィールドに付けます。
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User {
int id;
String name;
@JsonKey(includeIfNull: false)
String email;
User({this.id, this.name, this.email});
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
final yamada = User(
id: "0001",
name: "Yamada Dai",
email: "yamada@example.com",
);
final tanaka = User(
id: "0002",
name: "Tanaka Hiroshi",
);
// {id: 0001, name: Yamada Dai, email: yamada@example.com}
print(yamada.toJson());
// {id: 0002, name: Tanaka Hiroshi}
print(tanaka.toJson());
デフォルト値を設定したい
APIレスポンスがnullで返ってきて、アプリケーションではnon nulllで扱いたいときに、@JsonKey(defaultValue: '')
で初期値を設定できます。
import 'package:json_annotation/json_annotation.dart';
part 'food.g.dart';
@JsonSerializable()
class Food {
final String id;
@JsonKey(defaultValue: '')
final String name;
Food({
required this.id,
required this.name,
});
factory Food.fromJson(Map<String, dynamic> json) => _$FoodFromJson(json);
Map<String, dynamic> toJson() => _$FoodToJson(this);
}
// キーがなくても大丈夫
final json1 = {
"id": "0001",
};
final json2 = {
"id": "0001",
"name": null,
};
List型をJsonから変換時、アイテムがない場合にエラーになる
これも同じくdefaultValueで解決できました。
import 'package:json_annotation/json_annotation.dart';
part 'example.g.dart';
@JsonSerializable()
class Example {
@JsonKey(defaultValue: [])
List<String> items;
Example({required this.items});
factory Example.fromJson(Map<String, dynamic> json) =>
_$ExampleFromJson(json);
Map<String, dynamic> toJson() => _$ExampleToJson(this);
}
オブジェクトが入れ子になったクラス
複雑なJsonのパースは、専用のメソッドを定義し、@JsonKey(fromJson: _addressFromJson, toJson: _addressToJson)
という形で指定することで、パースできるようになります。
import 'package:json_annotation/json_annotation.dart';
@JsonSerializable()
class Person {
String name;
int age;
@JsonKey(fromJson: _addressFromJson, toJson: _addressToJson)
Address address;
Person({this.name, this.age, this.address});
factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
Map<String, dynamic> toJson() => _$PersonToJson(this);
static Address _addressFromJson(Map<String, dynamic> json) {
return json == null ? null : Address.fromJson(json);
}
static Map<String, dynamic> _addressToJson(Address address) =>
address?.toJson();
}
@JsonSerializable()
class Address {
String street;
String city;
Address({this.street, this.city});
factory Address.fromJson(Map<String, dynamic> json) =>
_$AddressFromJson(json);
Map<String, dynamic> toJson() => _$AddressToJson(this);
}
Jsonに含めたくない
Jsonに含めたくない場合は@JsonKey(ignore: true)
を指定しましょう。
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User {
int id;
String name;
@JsonKey(ignore: true)
String email;
User({this.id, this.name, this.email});
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
おわりに
JsonKeyには他にも設定できる値があり、カスタマイズしていけそうです。
また、開発していく上で使えそうなものがあれば、記事を更新していきたいと思います!