4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Flutter】json_serializable を使ってみた

Last updated at Posted at 2023-05-20

json_serializable とは

こちら。

APIなどから取得したJSON文字列を、クラスに変換するとき、

    final jsonString = '{"id":123, "name":"THE BOOK", "price":1500, "author":{"id":999, "name":"sato"}}';

    final jsonStringMap1 = jsonDecode(jsonString);
    final author1 = Author(id: jsonStringMap1['author']['id'], name: jsonStringMap1['author']['name']);
    final person1 = Book(id: jsonStringMap1['id'], name: jsonStringMap1['name'], author: author1);
    print('id: ${person1.id}');
    print('name: ${person1.name}');
    print('price: ${person1.price}');
    print('author_id: ${person1.author?.id}');
    print('author_name: ${person1.author?.name}');

のように jsonDecode() でMap型に変換し、
コンストラクタで、取得したMap型と対象クラスの変数とのマッピングを行い、クラス化する。

この「取得したMap型と対象クラスの変数とのマッピングを行い」部分のコードを自動生成してくれるのが、json_serializable
(例として Map型をクラスに変換する部分を扱うが、クラスをMap型に変換する部分のマッピングにも対応している。)

使い方

pubspec.yaml にパッケージを追加

dependencies:
  json_annotation: ^4.8.1

dev_dependencies:
  build_runner: ^2.4.4
  json_serializable: ^6.7.0

json_annotation のアノテーションを使用して、 build_runner で生成するので3種類必要。

値を格納するクラスを用意

import 'package:flutter_json_serializable/utils/author.dart';
import 'package:json_annotation/json_annotation.dart';

part 'book.g.dart';

@JsonSerializable()
class Book {
    final id;
    final name;
    final price;
    final Author? author;

    Book({this.id, this.name, this.price, this.author});

    factory Book.fromJson(Map<String, dynamic> json) => _$BookFromJson(json);

    Map<String, dynamic> toJson() => _$BookToJson(this);
}
import 'package:json_annotation/json_annotation.dart';

part 'author.g.dart';

@JsonSerializable()
class Author {
    final id;
    final name;

    Author({this.id, this.name});

    factory Author.fromJson(Map<String, dynamic> json) => _$AuthorFromJson(json);

    Map<String, dynamic> toJson() => _$AuthorToJson(this);
}

上から説明

  • import 'package:json_annotation/json_annotation.dart'; で json_annotation をインポート
  • part '【ファイル名を「.g.dart」拡張子にしたもの】'; を記載して、生成されるファイルと紐付ける
    (「ファイル名を「.g.dart」拡張子にした」ファイル名で生成される)
  • @JsonSerializable() で生成対象のクラス、という目印をつける
  • 必要な変数とコンストラクタを記載
    • 基本は変数名とJSONのキー文字列がイコール
      • build.yamlJsonKey を使用して別の文字列とのマッピングにすることもできるが割愛
    • 型を指定しないとJSON文字列から直接変換しようとするので、Bookクラスのauthorのみちゃんと型(Author)を指定している
  • factory 【クラス名】.fromJson(Map<String, dynamic> json) => _$【クラス名】FromJson(json); を記載することでMap型からクラスへのマッピングメソッドを生成
    • 【クラス名】.fromJson(【Map型】) をコンストラクタとして使用できる
  • Map<String, dynamic> toJson() => _$【クラス名】ToJson(this); を記載することでクラスからMap型へのマッピングメソッドを生成
  • 今回のように階層が複数ある場合は、階層ごとにマッピング用のクラスが必要となる

:warning: 生成後のファイルを参照してる部分もあるのでこの時点でエラーが出てるのは気にせず次に進む

コード生成

flutter pub run build_runner build

これを叩くことにより、

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'book.dart';

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

Book _$BookFromJson(Map<String, dynamic> json) => Book(
      id: json['id'],
      name: json['name'],
      price: json['price'],
      author: json['author'] == null
          ? null
          : Author.fromJson(json['author'] as Map<String, dynamic>),
    );

Map<String, dynamic> _$BookToJson(Book instance) => <String, dynamic>{
      'id': instance.id,
      'name': instance.name,
      'price': instance.price,
      'author': instance.author,
    };
// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'author.dart';

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

Author _$AuthorFromJson(Map<String, dynamic> json) => Author(
      id: json['id'],
      name: json['name'],
    );

Map<String, dynamic> _$AuthorToJson(Author instance) => <String, dynamic>{
      'id': instance.id,
      'name': instance.name,
    };

のようなメソッドが自動生成されるので、

    final jsonString2 = '{"id":123, "name":"THE BOOK", "price":1500, "author":{"id":999, "name":"sato"}}';

    final person2 = Book.fromJson(jsonDecode(jsonString2));
    print('id: ${person2.id}');
    print('name: ${person2.name}');
    print('price: ${person2.price}');
    print('author_id: ${person2.author?.id}');
    print('author_name: ${person2.author?.name}');

のように使用できる。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?