Closed6
FlutterのREST APIクライアントを使ってみる
はじめに
Chopper, dio, json_serializable, freezedを使ってみる
Chopper
準備コマンド
dart create hello_chopper
cd hello_chopper
dart pub get chopper
dart pub get --dev build_runner chopper_generator
dart pub get
touch api.js
ソースコード
hello_chopper/bin/hello_chopper.dart
import 'package:chopper/chopper.dart';
part "hello_chopper.chopper.dart";
(baseUrl: "/todos")
abstract class TodosListService extends ChopperService {
static TodosListService create([ChopperClient? client]) =>
_$TodosListService(client);
()
Future<Response> getTodos();
}
Future<void> main() async {
final chopper = ChopperClient(
baseUrl: "http://localhost:8000",
services: [
TodosListService.create(),
],
);
final todosService = chopper.getService<TodosListService>();
final response = await todosService.getTodos();
if (response.isSuccessful) {
final body = response.body;
print(body);
} else {
final code = response.statusCode;
final error = response.error;
print("code = $code, error = $error");
}
}
api.js
const http = require('http');
const server = http.createServer();
server.on('request', (req, res) => {
const content = JSON.stringify([
{title: 'Todo 1', completed: true},
{title: 'Todo 2', completed: false},
{title: 'Todo 3', completed: false},
], null, 2);
res.writeHead(200, {
'Content-Type': 'application/json',
'Content-Length': '' + content.length,
});
res.write(content);
res.end();
})
const port = parseInt(process.env.PORT || '8000', 10);
server.listen(port, () => console.info(`Listening on ${port}`));
実行コマンド
dart pub run build_runner build
dart run
実行結果
[
{
"title": "Todo 1",
"completed": true
},
{
"title": "Todo 2",
"completed": false
},
{
"title": "Todo 3",
"completed": false
}
]
コメント
Chopperは公式ドキュメントが充実してなくて初心者にはつらい
dio
準備コマンド
dart create hello_dio
cd hello_dio
dart pub add dio
dart pub get
touch api.js
コード
hello_dio/bin/hello_dio.dart
import 'package:dio/dio.dart';
Future<void> main() async {
try {
final response = await Dio().get("http://localhost:8000/todos");
print(response);
print(response.data[0]["title"]);
} catch (err) {
print(err);
}
}
api.js
const http = require('http');
const server = http.createServer();
server.on('request', (req, res) => {
const content = JSON.stringify([
{title: 'Todo 1', completed: true},
{title: 'Todo 2', completed: false},
{title: 'Todo 3', completed: false},
], null, 2);
res.writeHead(200, {
'Content-Type': 'application/json',
'Content-Length': '' + content.length,
});
res.write(content);
res.end();
})
const port = parseInt(process.env.PORT || '8000', 10);
server.listen(port, () => console.info(`Listening on ${port}`));
実行コマンド
dart run
実行結果
[{title: Todo 1, completed: true}, {title: Todo 2, completed: false}, {title: Todo 3, completed: false}]
Todo 1
コメント
dioはJavaScriptのfetch並みに使いやすい
でもJSONデコードなどはどうすれば良いのだろうか...
調べたところなんとJSONはデフォルトでMapにエンコードされる、すごい!
あとはjson_serializableやfreezedなどのパーサーを使えば良さそう
json_serializable
準備コマンド
dart create hello_json_serializable
cd hello_json_serializable
hello_json_serializable/pubspec.yaml
dependencies:
json_annotation: ^4.7.0
dev_dependencies:
build_runner: ^2.0.0
json_serializable: ^6.0.0
コード
hello_json_serializable/bin/hello_json_serializable.dart
import 'dart:convert';
import 'package:json_annotation/json_annotation.dart';
part 'hello_json_serializable.g.dart';
()
class Person {
final String firstName, lastName;
final DateTime? dateOfBirth;
Person({
required this.firstName,
required this.lastName,
this.dateOfBirth,
});
factory Person.fromJson(Map<String, dynamic> json) {
return _$PersonFromJson(json);
}
Map<String, dynamic> toJson() {
return _$PersonToJson(this);
}
}
void main() {
final person = Person(
firstName: "Tatsuya",
lastName: "Susukida",
dateOfBirth: DateTime(1987, 8, 27),
);
final encoded = jsonEncode(person.toJson());
print(encoded);
final decoded = Person.fromJson(jsonDecode(encoded));
print(decoded.firstName);
print(decoded.lastName);
print(decoded.dateOfBirth);
}
実行コマンド
dart run build_runner build
dart run
実行結果
{"firstName":"Tatsuya","lastName":"Susukida","dateOfBirth":"1987-08-27T00:00:00.000"}
Tatsuya
Susukida
1987-08-27 00:00:00.000
メモ
Flutter公式ドキュメントにJSONエンコード/デコードに関するページがある
freezed
準備コマンド
dart create hello_freezed
cd hello_freezed
dart pub add freeze_annotation json_annotation
dart pub add --dev build_runner freezed json_serializable
コード
import 'dart:convert';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'hello_freezed.freezed.dart';
part 'hello_freezed.g.dart';
@freezed
class Person with _$Person {
const factory Person({
required String firstName,
required String lastName,
required int age,
}) = _Person;
factory Person.fromJson(Map<String, Object?> json) => _$PersonFromJson(json);
}
void main() {
final person = Person(
firstName: 'Tatsuya',
lastName: 'lastName',
age: 35,
);
final copied = person.copyWith();
final encoded = jsonEncode(person.toJson());
final decoded = Person.fromJson(jsonDecode(encoded));
print(person);
print(person == copied);
print(encoded);
print(decoded);
}
実行コマンド
dart run build_runner build
dart run
実行結果
Person(firstName: Tatsuya, lastName: lastName, age: 35)
true
{"firstName":"Tatsuya","lastName":"lastName","age":35}
Person(firstName: Tatsuya, lastName: lastName, age: 35)
メモ
公式ドキュメントの内容が充実していて素晴らしい
fromJsonには=>
を使用する必要がある
Freezed will only generate a fromJson if the factory is using =>.
おわりに
以上で一旦クローズ、次はデータ管理パッケージを使ってみる
このスクラップは2023/01/10にクローズされました