クラスにtoJSONとformJSONなぜつける
わかりやすく解説
DartのクラスにtoJSONとfromJSONメソッドを追加することは、オブジェクトのシリアライズ(直列化)とデシリアライズ(逆シリアライズ)を行うための一般的な手法です。これらのメソッドは、オブジェクトをJSON形式に変換して保存したり、逆にJSONデータをオブジェクトに戻したりする際に使用されます。
具体的な理由としては以下のようなものが挙げられます:
データの永続化: JSONはデータの永続化に一般的に使用される形式です。DartのクラスをJSONに変換することで、オブジェクトの状態を保存し、必要に応じて後で再構築できます。
ネットワーク通信: クライアントとサーバー間の通信において、JSONは一般的に使用されるデータ形式です。オブジェクトをJSONに変換して送信し、受信したJSONをオブジェクトに変換することで、データの送受信が容易になります。
ライブラリやフレームワークの互換性: 多くのDartのライブラリやフレームワークは、オブジェクトのシリアライズとデシリアライズにJSONを使用しています。toJSONとfromJSONメソッドを実装することで、これらのライブラリやフレームワークとの互換性を高めることができます。
toJSONメソッドは、オブジェクトのプロパティを適切な形式に変換し、JSONオブジェクトとして返す責任を持ちます。一方、fromJSONメソッドは、JSONオブジェクトを受け取り、そのデータを使って新しいインスタンスを生成する責任を持ちます。
これらのメソッドを実装することで、Dartのオブジェクトを簡単にシリアライズおよびデシリアライズできるようになります。これは、データの保存やネットワーク通信、さらには他のライブラリとの統合など、さまざまなシナリオで便利です。
使用例:
型に?をつける場合
class Person {
String? name;
int? age;
String? address;
Person({this.name, this.age, this.address});
factory Person.fromJson(Map<String, dynamic> json) {
return Person(
name: json['name'],
age: json['age'],
address: json['address'],
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'age': age,
'address': address,
};
}
}
このコードで?がプロパティの型の後に付けられている理由は、DartのNull Safety(非null安全性)機能に関係しています。
DartのNull Safetyは、変数やプロパティがnullを許容するかどうかを静的にチェックする機能です。?は、変数やプロパティがnullを許容することを示すために使用されます。つまり、String?はnullまたはString型の値を持つことができることを意味します。
上記のコードでは、name、age、addressのプロパティに?が付いていることで、これらのプロパティがnullを許容することが宣言されています。これは、JSONデータが欠損している場合や、値が存在しない場合にプロパティがnullとなる可能性があることを意味します。
例えば、以下のようなJSONデータがあるとします:
{
"name": "John Doe",
"age": null,
"address": "123 Street, City"
}
このJSONデータをfromJsonメソッドでデシリアライズする場合、ageがnullであるため、プロパティageにはnullがセットされます。もしageの型がintであれば、nullを代入することはできず、コンパイルエラーが発生します。しかし、int?という型を使用することで、nullを許容することができ、問題なくデシリアライズが行われます。
同様に、toJsonメソッドでもプロパティがnullの場合に対応するため、プロパティの型に?が付いています。JSONオブジェクトに変換する際に、nullのプロパティはnull値として表現されます。
Null Safetyにより、コードの安全性と信頼性が向上し、nullに関連するエラーやバグを防ぐことができます。?を使ってプロパティのnull許容性を宣言することで、明示的にnullを許容することができるため、柔軟なコードを記述することができます。
requiredをつける場合
class Person {
String name;
int age;
String address;
Person({required this.name, required this.age, required this.address});
factory Person.fromJson(Map<String, dynamic> json) {
return Person(
name: json['name'],
age: json['age'],
address: json['address'],
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'age': age,
'address': address,
};
}
}
このコードでは、Null Safety機能を使用しておらず、プロパティの型に?が付いていないため、プロパティはnullを許容しません。また、コンストラクタの引数にはrequiredキーワードが付いており、それぞれの引数は必須となっています。
例えば、以下のようなJSONデータがあるとします:
{
"name": "John Doe",
"age": 30,
"address": "123 Street, City"
}
このJSONデータをfromJsonメソッドでデシリアライズする場合、プロパティname、age、addressに対して値が正しくセットされます。JSONデータが欠損していたり、値が存在しない場合は、デシリアライズ時に例外がスローされます。
また、toJsonメソッドでは、プロパティの値をそのまま返します。特にNull Safetyが有効でないため、プロパティがnullである場合は、nullを含むJSONオブジェクトが生成されます。
以下は、このコードの使用例です:
class Person {
String name;
int age;
String address;
Person({required this.name, required this.age, required this.address});
factory Person.fromJson(Map<String, dynamic> json) {
return Person(
name: json['name'],
age: json['age'],
address: json['address'],
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'age': age,
'address': address,
};
}
}
void main() {
// JSONデータ
Map<String, dynamic> jsonData = {
'name': 'John Doe',
'age': 30,
'address': '123 Street, City',
};
// JSONからPersonオブジェクトにデシリアライズ
Person person = Person.fromJson(jsonData);
// PersonオブジェクトをJSONにシリアライズ
Map<String, dynamic> personJson = person.toJson();
// 結果の出力
print('Name: ${person.name}');
print('Age: ${person.age}');
print('Address: ${person.address}');
print('Serialized JSON: $personJson');
}
実行結果
Name: John Doe
Age: 30
Address: 123 Street, City
Serialized JSON: {name: John Doe, age: 30, address: 123 Street, City}
この例では、JSONデータの各プロパティが正しくデシリアライズされ、Personオブジェクトのプロパティに値がセットされます。また、toJsonメソッドを使用してPersonオブジェクトをJSONデータにシリアライズすることができます。
まとめ
今回のポイントは、
でした。
Discussion
?は変数じゃなくて型に付いてるものですね
ひええええ
修正しました😱
いつも記事を見ていただきありがとうございます!