search
LoginSignup
41
Help us understand the problem. What are the problem?

Flutter #2 Advent Calendar 2018 Day 22

posted at

updated at

FlutterでJSONデータのHTTP通信

(2021/12/12追記)以下の記事の情報は古いです。Freezedを使用しましょう。

はじめに

FlutterでJSONデータのHTTP通信をする方法に関しては公式のドキュメントで基本的な説明があります。
しかし、JSONをリクエストパラメータとしてPOSTする部分の記載が無かったので、そこを簡単に説明をしようと思います。

コード

モデルクラスをJSON化してencodeしたものをbodyで渡します。
あとはヘッダーのContent-Typeをapplication/jsonにする事を忘れずに。

class SampleRequest {
  final String key;
  final int order;

  SampleRequest({
    this.key,
    this.order
  });

  Map<String, dynamic> toJson() => {
    'key': key,
    'order': order,
  };
}

class SampleResponse {
  final number sampleId;
  final String sampleName;

  SampleResponse({
    this.sampleId,
    this.sampleName
  });

  factory SampleResponse.fromJson(Map<String, dynamic> json) {
    return Spot(
      sampleId: json['sampleId'],
      sampleName: json['sampleName'],
    );
  }
}

Future<SampleResponse> _requestSample() async {
  var url = "http://example.com/sample"
  var request = new SampleRequest(key: "key", order: 0);
  final response = await http.post(url,
      body: json.encode(request.toJson()),
      headers: {"Content-Type": "application/json"});

  if (response.statusCode == 200) {
    // If server returns an OK response, parse the JSON
    return SampleResponse.fromJson(json.decode(response.body));
  } else {
    // If that response was not OK, throw an error.
    throw Exception('Failed to load post');
  }
}

といった感じのコードになります。

さいごに

つい先日、Flutter製のアプリを無事リリースする事ができました。
知り合いが開発するKoretteというWebサービスのアプリ版です。
ダウンロードはこちらから。観光地や地域にスポットを当てたクイズアプリです。ぜひ遊んでみてください!
iphone_1.jpg

おまけ

HTTP通信のモデルクラスを各API毎にゴリゴリ描いてたら、パラメータの多い時にとんでもなく大変でした。
例えばパラメータが10個あればコンストラクタやtoJsonやfromJsonで40行と中々の量に...

spot.dart
class Spot {
  final num id;
  final String spotName;
  final String spotDescription;
  final String adress;
  final num latitude;
  final num longitude;
  final num townId;
  final String townName;
  final num prefectureId;
  final String prefectureName;

  Spot({
    this.id, 
    this.spotName, 
    this.spotDescription, 
    this.adress, 
    this.latitude, 
    this.longitude, 
    this.townId, 
    this.townName, 
    this.prefectureId, 
    this.prefectureName, 
  });

  factory Spot.fromJson(Map<String, dynamic> json) {
    return Spot(
      id: json['id'],
      spotName: json['spotName'],
      spotDescription: json['spotDescription'],
      adress: json['adress'],
      latitude: json['latitude'],
      longitude: json['longitude'],
      townId: json['townId'],
      townName: json['townName'],
      prefectureId: json['prefectureId'],
      prefectureName: json['prefectureName'],
    );
  }

  Map<String, dynamic> toJson() => {
    'id': id,
    'spotName': spotName,
    'spotDescription': spotDescription,
    'adress': adress,
    'latitude': latitude,
    'longitude': longitude,
    'townId': townId,
    'townName': townName,
    'prefectureId': prefectureId,
    'prefectureName': prefectureName,
  };
}

この地味に苦しい繰り返し作業はrubyでコンバータを適当に作って解決しました。
converter.rb
これを使用すると、

spot.dart
class Spot {
  final num id;
  final String spotName;
  final String spotDescription;
  final String adress;
  final num latitude;
  final num longitude;
  final num townId;
  final String townName;
  final num prefectureId;
  final String prefectureName;
}

とだけ書いて、
ruby coverter.rb spot.dart
というコマンドを叩けば、上記のコンストラクタやtoJsonやfromJsonが含まれたdartファイルが生成されます。
無駄な改行とかあると動かないかもしれないので注意してください。

そんなこんなで自動化してたわけですが、後から調べたらjson_annotationというpackageがあって、それを使用すれば十分かもしれません。

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
What you can do with signing up
41
Help us understand the problem. What are the problem?