FlutterでのJSON解析

25234 ワード

JSONは私たちの開発で最もよく使われているデータフォーマットです.この文章では、主に開発で最もよく見られるいくつかのフォーマットのJSONデータのFlutterでの解析を見てみましょう.
次の例では、jsonファイルをローカル、すなわちassetsファイルに配置し、ローカルからこれらのファイルを読み込んで解析します.
必要に応じてassets/person.json:
では、pubspec.yamlでは、次のように構成する必要があります.
flutter:
	uses-material-design:  true
	#       
	assets:
		-  assets/person.json

次に、一般的なJson形式のデータを解析します.
Dartの基礎についてまだよく知らない場合は、まずこの文章を見てみましょう.
単純なオブジェクト解析
personを定義します.jsonは以下の通りです.
{
	"name":  "jack",
	"age":  18,
	"height":  175.0
}

Javaと同様に、Personのエンティティクラスを構築する必要があります.以下のようにします.
class Person {
  String name;
  int age;
  double height;

  Person({this.name, this.age, this.height});

  factory Person.fromJson(Map<String, dynamic> json) {
    return Person(name: json['name'], age: json['age'], height: json['height']);
  }
}

次にpersonを作成しますservice.ダートはpersonを解析するjson.
このクラスには、次の依存ライブラリをインポートする必要があります.
//        rootBundle       perosn.json   
import 'package:flutter/services.dart';  
// json
import 'dart:convert';  
//    Future
import 'dart:async';

person_service.dart
import 'package:flutter/services.dart';
import 'dart:convert';
import 'dart:async';
import '../models/person.dart';

//    assets       person.json   
Future<String> _loadPersonJson() async {
  return await rootBundle.loadString('assets/person.json');
}

//   json        Person   
Future decodePerson() async {
  //       json    
  String personJson = await _loadPersonJson();

  //    json    ,     Map   
  final jsonMap = json.decode(personJson);

  print('jsonMap runType is ${jsonMap.runtimeType}');

  Person person = Person.fromJson(jsonMap);

  print(
      'person name is ${person.name}, age is ${person.age}, height is ${person.height}');

  return person;
}

次のように入力します.
flutter: jsonMap runType is _InternalLinkedHashMap<String, dynamic>
flutter: person name is jack, age is 18, height is 175.0
json.decode(personJson)メソッドが返すタイプは_InternalLinkedHashMapであることがわかります.このMapのkeyはStringタイプであり、valueのタイプはdynamicであり、すなわち動的であり、例えばperson.jsonではkeyはStringタイプですが、valueはString、int、doubleなどのタイプである可能性があります.
配列を含むオブジェクト
countryを定義します.jsonは以下の通りです.
{
    "name": "China",
    "cities": [
        "Beijing",
        "Shanghai"
    ]
}

エンティティークラスは次のとおりです.
class Country {  
  String name;  
  List<String> cities;  
  
  Country({this.name, this.cities});  
  
  factory Country.fromJson(Map<String, dynamic> json) {  
  return Country(name: json['name'], cities: json['cities']);  
  }  
}

サービスクラスは次のとおりです.
import 'dart:async';
import 'package:flutter/services.dart';
import 'dart:convert';
import '../models/country.dart';

Future<String> _loadCountryJson() async {
  return await rootBundle.loadString('assets/country.json');
}

Future decodeCountry() async {
  String countryJson = await _loadCountryJson();

  Map<String, dynamic> jsonMap = json.decode(countryJson);

  Country country = Country.fromJson(jsonMap);
  print('country name is ${country.name}');
  return country;
}

そしてmain()でdecodeCountry()を呼び出して実行し、エラーを報告しました...
Unhandled Exception: type 'List' is not a subtype of type 'List'
...

エラー・ログでは、ListListのサブタイプではありません.つまり、countryのエンティティ・クラスでcities属性に直接cities: json['cities']を割り当てます.まず、json['cities']がどのようなタイプかを見てみましょう.
factory Country.fromJson(Map<String, dynamic> json) {  
  print('json["cities"] type is ${json['cities'].runtimeType}');  
  return Country(name: json['name'], cities: json['cities']);  
}

出力は次のとおりです.
flutter: json["cities"] type is List

この場合、Country.fromJson(...)メソッドを次のように変更する必要があります.
factory Country.fromJson(Map<String, dynamic> json) {
    print('json["cities"] type is ${json['cities'].runtimeType}');
    var originList = json['cities'];
    List<String> cityList = new List<String>.from(originList);
    return Country(name: json['name'], cities: cityList);
  }

上記のコードでは、Listタイプの配列を作成し、List配列の要素をListに追加しました.出力は次のとおりです.
flutter: json["cities"] type is List
flutter: country name is China

オブジェクトのネスト
shapeを定義します.json、フォーマットは以下の通りです.
{  
  "name": "rectangle",  
  "property": {  
  "width": 5.0,  
  "height": 10.0  
  }  
}

エンティティは次のとおりです.
class Shape {  
  String name;  
  Property property;  
  
  Shape({this.name, this.property});  
  
  factory Shape.fromJson(Map<String, dynamic> json) {  
  return Shape(name: json['name'], property: json['property']);  
  }  
}  
  
class Property {  
  double width;  
  double height;  
  
  Property({this.width, this.height});  
  
  factory Property.fromJson(Map<String, dynamic> json) {  
  return Property(width: json['width'], height: json['height']);  
  }  
}

サービスクラスは次のとおりです.
import 'dart:async';  
import 'dart:convert';  
import 'package:flutter/services.dart';  
import '../models/shape.dart';  
  
Future<String> _loadShapeJson() async {  
  return await rootBundle.loadString('assets/shape.json');  
}  
  
Future decodeShape() async {  
  String shapeJson = await _loadShapeJson();  
  
  Map<String, dynamic> jsonMap = json.decode(shapeJson);  
  
  Shape shape = Shape.fromJson(jsonMap);  
  
  print('shape name is ${shape.name}');  
  return shape;  
}

実行後、次のエラーが表示されます.
Unhandled Exception: type '_InternalLinkedHashMap' is not a subtype of type 'Property'

すなわち、property: json['property']ここで付与される値のタイプは_InternalLinkedHashMapではなくPropertyであり、json['property']の値はこのような{width: 5.0, height: 10.0}であり、それはMapであり、Propertyのオブジェクトではない.私たちはまずこのMapをオブジェクトに変換し、その後、付与する必要がある.
factory Shape.fromJson(Map<String, dynamic> json) {  
  print('json["property"] is ${json['property']}');  
  Property property = Property.fromJson(json['property']);   // new line
  return Shape(name: json['name'], property: property);  
}

出力:
shape name is rectangle

複雑なオブジェクト配列のネスト
{
  "id": "0302",
  "class_name": "    ",
  "students": [
    {
      "name": "   ",
      "sex": " "
    },
    {
      "name": "   ",
      "sex": " "
    }
  ]
}

エンティティ:
class ClassInfo {
  String id;
  String name;
  List studentList;

  ClassInfo({this.id, this.name, this.studentList});

  factory ClassInfo.fromJson(Map<String, dynamic> json) {
    return ClassInfo(
        id: json['id'],
        name: json['class_name'],
        studentList: json['students']);
  }
}

class Student {
  String name;
  String sex;

  Student({this.name, this.sex});

  factory Student.fromJson(Map<String, dynamic> json) {
    return Student(name: json['name'], sex: json['sex']);
  }
}

service:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/services.dart';
import '../models/class_info.dart';

Future<String> _loadClassInfoJson() async {
  return await rootBundle.loadString('assets/class_info.json');
}

Future decodeClassInfo() async {
  String classInfoJson = await _loadClassInfoJson();

  Map<String, dynamic> jsonMap = json.decode(classInfoJson);

  ClassInfo classInfo = ClassInfo.fromJson(jsonMap);
  classInfo.studentList
      .forEach((student) => print('student name is ${student.name}'));
  return classInfo;
}

上記のコードは、実行後もエラーが発生します.
Unhandled Exception: type 'List' is not a subtype of type 'List'

同様に、やはりstudentList: json['students']に問題が発生しました.json['students']の負けを見てみましょう.
[{name:    , sex:  }, {name:    , sex:  }]

上記の結果のタイプはListである.次に、ListListタイプの配列に変換する必要があります.ここでは、オペレータmapを使用する必要があります.mapオペレータの役割は、あるタイプを別のタイプに変換することです.次のようになります.
factory ClassInfo.fromJson(Map<String, dynamic> json) {  
  final originList = json['students'] as List;  
  List studentList =  
      originList.map((value) => Student.fromJson(value)).toList();  
  return ClassInfo(  
  id: json['id'], name: json['class_name'], studentList: studentList);  
}

出力:
flutter: student name is    
flutter: student name is    

単純な配列
member.json
[
  {
    "id": 1,
    "name": "Jack"
  },
  {
    "id": 2,
    "name": "Rose"
  },
  {
    "id": 3,
    "name": "Karl"
  }
]

エンティティ:
class MemberList {  
  List memberList;  
  
  MemberList({this.memberList});  
  
  factory MemberList.fromJson(List<dynamic> listJson) {  
  
  List memberList =  
        listJson.map((value) => Member.fromJson(value)).toList();  
  
  return MemberList(memberList: memberList);  
  }  
}  
  
class Member {  
  int id;  
  String name;  
  
  Member({this.id, this.name});  
  
  factory Member.fromJson(Map<String, dynamic> json) {  
  return Member(id: json['id'], name: json['name']);  
  }  
}

なぜならjsonは単純な配列であるため,上記のコードではこのメンバー配列を含むメンバーリストクラスを作成した.
上記のコードのMemberList.fromJson(...)の書き方に注意してください.
service:
import 'dart:async';
import 'package:flutter/services.dart';
import 'dart:convert';
import '../models/member.dart';

Future<String> _loadMemberJson() async {
  return await rootBundle.loadString('assets/member.json');
}

Future decodeMemberList() async {
  String memberListJson = await _loadMemberJson();

  List<dynamic> list = json.decode(memberListJson);

  MemberList memberList = MemberList.fromJson(list);

  memberList.memberList
      .forEach((member) => print('member name is ${member.name}'));

  return memberList;
}

出力:
flutter: member name is Jack
flutter: member name is Rose
flutter: member name is Karl

複雑なJson解析
先の記事FlutterではListViewの使用に豆弁APIが使われていましたが、このAPIで返されたデータには現在ヒットしている映画が含まれていますので、必要に応じて解析してみてください!!
間違いがあれば、指摘してください.ありがとう!
ソースアドレス
参照リンク:
medium.com/flutter-com…
github.com/flutter/flu…
転載先:https://juejin.im/post/5c98a5ed51882520f2089450