質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Q&A

解決済

3回答

562閲覧

JSONのパースについて

退会済みユーザー

退会済みユーザー

総合スコア0

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

0グッド

0クリップ

投稿2022/12/23 04:17

dio + freezedを最近になって触り始めましたが解決方法が見つからず困っています
解決方法をご教示いただけないでしょうか?

実現したいこと

以下のようなJSONをパースして、下記の例にある[key1]や[key2]だけでなく
[subkey]の値にもアクセスしたいです

{ "data": [ { "key1": "data", "key2": "data", "key3": [ { "subkey11": "data", "subkey12": "data", "subkey13": "data" }, { "subkey21": "data", "subkey22": "data", "subkey23": "data" } ] }, { "key1": "data", "key2": "data", "key3": [ { "subkey11": "data", "subkey12": "data", "subkey13": "data" }, { "subkey21": "data", "subkey22": "data", "subkey23": "data" } ] } ] }

該当のソースコード

key「data」までは 「List<dynamic> data = map["data"];」と書く事でパース出来る事はわかりましたが
subkeyが文字列になってしまいます。

HTTP通信(DIO)

1 Future<List<mdl>?> fetchList() async { 2 const url = 'https://dummy.com/dummy'; 3 final response = await dio.get( 4 url, 5 options: Options(headers: { 6 "Content-Type": "application/json", 7 }), 8 ); 9 10 if (response.statusCode == 200) { 11 try { 12 Map<String, dynamic> map = Map<String, dynamic>.from(response.data); 13 List<dynamic> data = map["data"]; 14 final list = data.map((e) => mdl.fromJson(e)).toList(); 15 return list; 16 } catch (e) { 17 throw e; 18 } 19 } else { 20 return null; 21 } 22 } 23}

ListView

1 return Scaffold( 2 body: Center( 3 child: asyncValue.when( 4 data: (data) { 5 return data.isNotEmpty 6 ? ListView( 7 children: data.map((mdl mdl) { 8 return Card( 9 child: GestureDetector( 10 onTap: () {}, 11 child: ListTile( 12 title: Text(mdl.key1.toString()), 13 ))); 14 }).toList(), 15 ) 16 : const Text('データはありません'); 17 }, 18 loading: () => const CircularProgressIndicator(), 19 error: (error, _) => Text(error.toString()), 20 ), 21 ), 22 );

補足情報(FW/ツールのバージョンなど)

Flutter 3.3.9 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b8f7f1f986 (4 weeks ago) • 2022-11-23 06:43:51 +0900
Engine • revision 8f2221fbef
Tools • Dart 2.18.5 • DevTools 2.15.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ta.fu

2022/12/23 11:47

[subkey]にアクセスしたいとは? Mapのキーに、"subkey11"とか"subkey12"を指定してJSONファイル書かれている"data"を取り出したいということですか。 次に「subkeyが文字列になってしまいます。」とは具体的にどう確認して文字列だったと判断したのでしょうか。
退会済みユーザー

退会済みユーザー

2022/12/23 19:13

>Mapのキーに、"subkey11"とか"subkey12"を指定してJSONファイル書かれている"data"を取り出したいということですか。 その通りです >確認して文字列だったと判断したのでしょうか。 runtimetypeでデータ形式を見ています。 データの中身を確認しましたが下記のようになります パースしていないので当然、JSONフォーマットを無視した1行の文字列になっています {subkey11:data,subkey12:data,subkey13:data},{subkey21:data,subkey22:data,subkey23:data}
guest

回答3

0

ta.fuさんへのレス続き
別に書きました通り、APIから取得するJSONのデータ個数は一定ではありません
ご指摘のやり方を踏襲しつつなんとか対応すると下記のようなイメージしか無さそうですが、
freezedを使う事でもう少しシンプルに書けないものかと思っての質問でした

return Scaffold( appBar: AppBar(title: const Text('')), body: Center( child: asyncValue.when( data: (data) { return data.isNotEmpty ? ListView.builder( itemCount: data.length, itemBuilder: (context, index) { var key3 = data[index].key3; return DataTable( headingRowHeight: 35, headingRowColor: MaterialStateProperty.resolveWith((states) => Colors.black12), columns: [ const DataColumn(label: Text("No")), const DataColumn(label: Text("氏名")), const DataColumn(label: Text("時間")), ], rows: List.generate(  key3.length, (count) => DataRow( color: MaterialStateProperty.all(index.isEven ? Colors.grey : Colors.black12), cells: [ DataCell(Text("${count + 1}")), DataCell(Text(emp[count]["subkey1"])), DataCell(Text("${output.format(DateTime.parse(key3[count]["subkey2"]))} 〜 ${output.format(DateTime.parse(key3[count]["subkey3"]))}")), ], ), ), ); }, ) : const Text('Data is empty.'); }, loading: () => const CircularProgressIndicator(), error: (error, _) => Text(error.toString()), ), ), ); } }

※ちなみに、subkey11や subkey21は例として不適当でしたので読み替えをお願い致します
subkey11 → subkey1 / subkey12 → subkey2
subkey21 → subkey1 / subkey22 → subkey2

投稿2022/12/29 15:47

編集2022/12/29 15:51
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

実現したいことに書かれている内容の答えであれば、response.data["data"][0]["key3"][0]["subkey11"]のように記述すればアクセスできるのだと思うけど。
dartのjsonエンコーダーは、[]内をListに、{}内をMapにして取り込んでるので、それを念頭に置いてアクセスすればデータを取り出せると思います。

ただコメントに対しての返答でruntimetypeが文字列(String)だと書かれているので、提示されていない情報に依存した問題があるのかもしれませんが。

以下のサンプルコードで試してます。
テスト用のローカルサーバーを立てて、該当するJSONデータを取得できるようにして、dioを使って読み込んだ結果を使用してます。

dart

1import 'dart:async'; 2import 'dart:convert'; 3import 'dart:io'; 4 5import 'package:dio/dio.dart'; 6 7HttpServer? _server; 8 9Encoding requiredEncodingForCharset(String charset) => 10 Encoding.getByName(charset) ?? 11 (throw FormatException('Unsupported encoding "$charset".')); 12 13Uri get serverUrl => Uri.parse('http://localhost:${_server?.port}'); 14 15/// Starts a new HTTP server. 16Future<void> startServer() async { 17 _server = (await HttpServer.bind('localhost', 0)) 18 ..listen((request) async { 19 var path = request.uri.path; 20 var response = request.response; 21 22 if (path == '/dummy') { 23 response.headers.contentType = ContentType('application', 'json'); 24 response 25 ..statusCode = 200 26 ..contentLength = -1 27 ..write(''' 28{ 29 "data": [ 30 { 31 "key1": "data", 32 "key2": "data", 33 "key3": [ 34 { 35 "subkey11": "data", 36 "subkey12": "data", 37 "subkey13": "data" 38 }, 39 { 40 "subkey21": "data", 41 "subkey22": "data", 42 "subkey23": "data" 43 } 44 ] 45 }, 46 47 { 48 "key1": "data", 49 "key2": "data", 50 "key3": [ 51 { 52 "subkey11": "data", 53 "subkey12": "data", 54 "subkey13": "data" 55 }, 56 { 57 "subkey21": "data", 58 "subkey22": "data", 59 "subkey23": "data" 60 } 61 ] 62 } 63 ] 64} 65'''); 66 response.close(); 67 return; 68 } 69 }); 70} 71 72/// Stops the current HTTP server. 73void stopServer() { 74 if (_server != null) { 75 _server!.close(); 76 _server = null; 77 } 78} 79 80void main(List<String> args) async { 81 await startServer(); 82 83 final dio = Dio(); 84 dio.options.baseUrl = serverUrl.toString(); 85 final response = await dio.get( 86 "/dummy", 87 options: Options(headers: { 88 "Content-Type": "application/json", 89 }), 90 ); 91 92 print(response.data["data"][0]["key3"][0]["subkey11"]); 93 stopServer(); 94}

投稿2022/12/24 01:09

ta.fu

総合スコア1664

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/12/29 15:25

コメントありがとうございます ただ、APIから受け取るJSONは個数が一定ではありません 長くなりそうなので続きは別に書きます
guest

0

ベストアンサー

以下のコードを、パースしたいJsonのモデルとなっているすべてのFreezedのClassの中に、記述すると出来ると思います。

dart

1 (anyMap: true)

それか、プロジェクトのルートディレクトリに”build.yaml”というファイルを作って以下の内容を記述してください

yaml

1targets: 2 $default: 3 builders: 4 json_serializable: 5 options: 6 any_map: true

投稿2022/12/23 09:48

children

総合スコア89

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/12/23 19:22

ありがとうございます 試してみます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問