JSON(外国語) → Dartオブジェクト(日本語)
JSONをDartオブジェクトに変換、データを扱いやすくする方法
目次
JSON って何?
JSON (JavaScript Object Notation) は、データをやり取りする形式
{
"id": 1,
"name": "田中太郎",
"fee": 8000,
"isPaid": true
}
- { } で囲まれている
- “キー”: 値 の形式
- 文字列は ” で囲む
- 数値・真偽値は囲まない
基本の変換
JSON → Dart(デコード):
import 'dart:convert';
// JSON文字列
String jsonString = '{"name": "田中太郎", "age": 25}';
// Map に変換
Map<String, dynamic> data = json.decode(jsonString);
print(data['name']); // 田中太郎
print(data['age']); // 25
Dart → JSON (エンコード):
// Map
Map<String, dynamic> data = {
'name': '田中太郎',
'age': 25,
};
// JSON文字列に変換
String jsonString = json.encode(data);
print(jsonString); // {"name":"田中太郎","age":25}
問題点: Map は使いにくい
// ❌ タイポしやすい
print(data['nmae']); // null (間違えてもエラーにならない)
// ❌ 型がわからない
var age = data['age']; // dynamic型
// ❌ 補完が効かない
data[''] // ← IDEが候補を出してくれない
解決策: モデルクラスを作る!
モデルクラスとは?
モデルクラスは、JSONデータをDartクラスに変換したもの!
基本形:
class Student {
final int id;
final String name;
final int fee;
final bool isPaid;
// ========================================
// コンストラクタ
// ========================================
Student({
required this.id,
required this.name,
required this.fee,
required this.isPaid,
});
// ========================================
// JSON → Student (fromJson)
// ========================================
factory Student.fromJson(Map<String, dynamic> json) {
return Student(
id: json['id'],
name: json['name'],
fee: json['fee'],
isPaid: json['isPaid'],
);
}
// ========================================
// Student → JSON (toJson)
// ========================================
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'fee': fee,
'isPaid': isPaid,
};
}
}
使い方:
// JSON文字列
String jsonString = '''
{
"id": 1,
"name": "田中太郎",
"fee": 8000,
"isPaid": true
}
''';
// JSON → Map
Map<String, dynamic> json = jsonDecode(jsonString);
// Map → Student
Student student = Student.fromJson(json);
// ✅ タイプセーフ!
print(student.name); // 田中太郎
print(student.fee); // 8000
print(student.isPaid); // true
// ✅ 補完が効く!
student. // ← IDEが候補を出してくれる!
// Student → JSON
Map<String, dynamic> data = student.toJson();
String output = json.encode(data);
リストの扱い
JSON配列:
[
{"id": 1, "name": "田中太郎", "fee": 8000, "isPaid": true},
{"id": 2, "name": "佐藤花子", "fee": 8000, "isPaid": false},
{"id": 3, "name": "鈴木一郎", "fee": 9000, "isPaid": true}
]
変換:
// JSON配列 → List<Student>
List<Student> parseStudents(String jsonString) {
final List<dynamic> jsonList = json.decode(jsonString);
return jsonList.map((json) => Student.fromJson(json)).toList();
}
// 使い方
String jsonString = '''
[
{"id": 1, "name": "田中太郎", "fee": 8000, "isPaid": true},
{"id": 2, "name": "佐藤花子", "fee": 8000, "isPaid": false}
]
''';
List<Student> students = parseStudents(jsonString);
for (var student in students) {
print(student.name);
}
API から取得:
Future<List<Student>> fetchStudents() async {
final url = Uri.parse('https://api.example.com/students');
final response = await http.get(url);
if (response.statusCode == 200) {
// JSON配列をデコード
final List<dynamic> jsonList = json.decode(response.body);
// List<Student> に変換
return jsonList.map((json) => Student.fromJson(json)).toList();
} else {
throw Exception('Failed to load students');
}
}
// 使い方
final students = await fetchStudents();
print('生徒数: ${students.length}');
便利なツール
- quicktype.io ⭐⭐⭐⭐⭐
JSONを貼り付けると、自動でモデルクラスを生成!
https://app.quicktype.io にアクセス
左にJSON貼り付け
右上で「Dart」を選択
右側にコードが生成される!
超便利! 😊
- json_serializable パッケージ
自動でfromJson/toJsonを生成!
dependencies:
json_annotation: ^4.8.1
dev_dependencies:
build_runner: ^2.4.0
json_serializable: ^6.7.0
import 'package:json_annotation/json_annotation.dart';
part 'student.g.dart'; // 自動生成されるファイル
@JsonSerializable()
class Student {
final int id;
final String name;
final int fee;
final bool isPaid;
Student({
required this.id,
required this.name,
required this.fee,
required this.isPaid,
});
// ========================================
// 自動生成される
// ========================================
factory Student.fromJson(Map<String, dynamic> json) =>
_$StudentFromJson(json);
Map<String, dynamic> toJson() => _$StudentToJson(this);
}
flutter pub run build_runner buildで
student.g.dart が自動生成される!
コツを調べてみた
as でキャスト
// ✅ 安全
factory Student.fromJson(Map<String, dynamic> json) {
return Student(
id: json['id'] as int, // int にキャスト
name: json['name'] as String, // String にキャスト
fee: json['fee'] as int,
);
}
// ❌ 危険
factory Student.fromJson(Map<String, dynamic> json) {
return Student(
id: json['id'], // dynamic型のまま
name: json['name'],
fee: json['fee'],
);
}
null チェック
factory Student.fromJson(Map<String, dynamic> json) {
return Student(
id: json['id'] as int,
name: json['name'] as String,
fee: json['fee'] as int,
// null許容フィールド
paidDate: json['paidDate'] != null
? DateTime.parse(json['paidDate'])
: null,
// デフォルト値
photoPath: json['photoPath'] as String? ?? '',
// リスト (null の場合は空リスト)
lessonRecords: (json['lessonRecords'] as List<dynamic>?)
?.map((e) => LessonRecord.fromJson(e))
.toList() ??
[],
);
}
エラーハンドリング
factory Student.fromJson(Map<String, dynamic> json) {
try {
return Student(
id: json['id'] as int,
name: json['name'] as String,
fee: json['fee'] as int,
isPaid: json['isPaid'] as bool,
);
} catch (e) {
print('JSONパースエラー: $e');
print('JSON: $json');
rethrow; // エラーを再スロー
}
}
フォルダ構成
lib/
models/
student.dart
lesson_record.dart
event.dart
venue.dart
services/
api_service.dart
screens/
student_list_page.dart
まとめ
基本の流れ:
- モデルクラスを作る
- fromJson メソッド(JSON → オブジェクト)
- toJson メソッド(オブジェクト → JSON)
- API からデータ取得
- fromJson で変換
ツール:
- quicktype.io: JSONから自動生成
- json_serializable: コード自動生成
一言まとめ:
モデルクラスでJSONをタイプセーフに!
fromJson で JSON → オブジェクト、
toJson でオブジェクト → JSON。
as でキャスト、null チェック、エラーハンドリングを忘れずに。
quicktype.io で自動生成が超便利!
