Flutter: сложная json сериализация. Разбор json строки для предоставления в пользовательский интерфейс - PullRequest
2 голосов
/ 17 июня 2020

Вот строка json, которую я получаю по HTTP-запросу. Цель состоит в том, чтобы отобразить объекты в соответствии с текущим днем ​​недели.

{
    "first_name": "First Name",
    "batch_name": "Batch 1",
    "enrolled_subjects": [
        "Subject 4",
        "Subject 5"
    ],
    "batch_timetable": {
        "Mon": {
            "Subject 4": [
                "6:00 PM - 7:00 PM"
            ],
            "Subject 5": [
                "5:00 PM - 6:00 PM",
                "7:00 PM - 8:00 PM"
            ],
            "Subject 6": [
                "8:00 PM - 9:00 PM"
            ]
        },
        "Tue": {
            "Subject 4": [
                "6:00 PM - 7:00 PM"
            ],
            "Subject 5": [
                "7:00 PM - 8:00 PM"
            ],
            "Subject 6": [
                "8:00 PM - 9:00 PM"
            ]
        }, ...so on upto "Sun"
    }
}

Как установить класс модели для этой json строки?

Я пробовал этот класс модели, но он дает следующую ошибку: type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, List<dynamic>>'

Я также пробовал класс модели с помощью quicktype, но думаю, что в этом случае это не сработает.

class HomePageModel {
  HomePageModel({
    this.firstName,
    this.batchName,
    this.subjects,
    this.timetable,
  });

  String firstName;
  String batchName;
  List<String> subjects;
  Map timetable;

  factory HomePageModel.fromJson(Map<String, dynamic> json) => HomePageModel(
        firstName: json["first_name"],
        batchName: json["batch_name"],
        subjects: List<String>.from(json["subjects"].map((x) => x)),
        timetable: Map.from(json["timetable"])
            .map((key, value) => MapEntry(key, value)),
      );

  Map<String, dynamic> toJson() => {
        "first_name": firstName,
        "batch_name": batchName,
        "subjects": List<dynamic>.from(subjects.map((x) => x)),
        "timetable":
            Map.from(timetable.map((key, value) => MapEntry(key, value))),
      };
}

Я использую FutureBuilder для отображения этих данных в пользовательском интерфейсе. Любая помощь будет принята с благодарностью.

Ответы [ 3 ]

1 голос
/ 18 июня 2020

Так далеко от json, который вы предоставили, я создал и пример для вас в формате listview, просто проверьте его.

следующий json, который вы предоставили:

{
    "first_name": "First Name",
    "batch_name": "Batch 1",
    "enrolled_subjects": [
        "Subject 4",
        "Subject 5"
    ],
    "batch_timetable": {
        "Mon": {
            "Subject 4": [
                "6:00 PM - 7:00 PM"
            ],
            "Subject 5": [
                "5:00 PM - 6:00 PM",
                "7:00 PM - 8:00 PM"
            ],
            "Subject 6": [
                "8:00 PM - 9:00 PM"
            ]
        },
        "Tue": {
            "Subject 4": [
                "6:00 PM - 7:00 PM"
            ],
            "Subject 5": [
                "7:00 PM - 8:00 PM"
            ],
            "Subject 6": [
                "8:00 PM - 9:00 PM"
            ]
        }
    }
}

На основе json я создал пользовательский интерфейс

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _isLoading = false;
  List<Timings> timingsList = List();

  Future<String> loadFromAssets() async {
    return await rootBundle.loadString('json/parse.json');
  }

  @override
  void initState() {
    super.initState();
    dataLoadFunction();
  }

  dataLoadFunction() async {
    setState(() {
      _isLoading = true;
    });
    String jsonString = await loadFromAssets();
    Map newStringMap = json.decode(jsonString);
    //print(newStringMap['batch_timetable']);

    newStringMap['batch_timetable'].forEach((key, value) {
      List<Subjects> subjectsList = List();

      print(key);

      // print(value);
      value.forEach((key, value) {
        print(key);
        print(value);
        List<dynamic> timingValue = List();
        timingValue.add(value);
        Subjects subjects = Subjects(subjectName: key, timings: timingValue);
        subjectsList.add(subjects);
      });

      Timings sampleObject = Timings(
        day: key,
        subjectList: subjectsList,
      );
      timingsList.add(sampleObject);
    });
    print(timingsList.length);


    setState(() {
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: _isLoading
            ? CircularProgressIndicator()
            : ListView.builder(
                itemCount: timingsList.length,
                shrinkWrap: true,
                itemBuilder: (BuildContext context, int index) {
                  return Card(
                    child: Column(
                      children: <Widget>[
                        Padding(
                          padding: const EdgeInsets.only(top:10,left:15),
                          child: Row(
                            children: <Widget>[
                              Text('Day :'),
                              Text(timingsList[index].day),
                            ],
                          ),
                        ),
                        Divider(color: Colors.grey,),
                        Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            Text(' Day wise Subjects are :'),
                            ListView.builder(
                              itemCount: timingsList[index].subjectList.length,
                              shrinkWrap: true,
                              itemBuilder: (BuildContext context, int i) {
                                return Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: <Widget>[
                                    Text(timingsList[index]
                                        .subjectList[i]
                                        .subjectName),
                                    for (int j = 0;
                                        j <
                                            timingsList[index]
                                                .subjectList[i]
                                                .timings
                                                .length;
                                        j++)
                                      Text(timingsList[index]
                                          .subjectList[i]
                                          .timings[j]
                                          .toString()),
                                  ],
                                );
                              },
                            )
                          ],
                        )
                      ],
                    ),
                  );
                },
              ),
      ),
    );
  }
}

class Timings {
  final String day;
  final List<Subjects> subjectList;

  Timings({
    this.day,
    this.subjectList,
  });
}

class Subjects {
  final String subjectName;
  final List<dynamic> timings;

  Subjects({this.subjectName, this.timings});
}

Я только что добавил данные, вы можете украсить его в соответствии с желаемым пользовательским интерфейсом:

Чего я достиг в этот код

1) Данные будут извлекаться динамически, так что даже если json изменится, они будут адаптироваться соответствующим образом.

2) Добавил их в формат представления списка, вы можете делать то, что вы хотите.

Предоставлен образец пользовательского интерфейса, который я сделал enter image description here

Сообщите мне, работает ли он.

0 голосов
/ 18 июня 2020

для метода отдыха:

import 'package:http/http.dart' as http;

Future<HomePageModel> restSample() async {
  var response = await http.get('your URL');
  var jsonResponse = json.decode(response.body);
  HomePageModel homePageModel = HomePageModel.fromJson(jsonResponse);
  return homePageModel;
}

для параметров расписания звонков:

homePageModel.batchTimetable.mon;
0 голосов
/ 17 июня 2020

используйте это:

class HomePageModel {
  String firstName;
  String batchName;
  List<String> enrolledSubjects;
  BatchTimetable batchTimetable;

  HomePageModel(
      {this.firstName,
      this.batchName,
      this.enrolledSubjects,
      this.batchTimetable});

  HomePageModel.fromJson(Map<String, dynamic> json) {
    firstName = json['first_name'];
    batchName = json['batch_name'];
    enrolledSubjects = json['enrolled_subjects'].cast<String>();
    batchTimetable = json['batch_timetable'] != null
        ? new BatchTimetable.fromJson(json['batch_timetable'])
        : null;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['first_name'] = this.firstName;
    data['batch_name'] = this.batchName;
    data['enrolled_subjects'] = this.enrolledSubjects;
    if (this.batchTimetable != null) {
      data['batch_timetable'] = this.batchTimetable.toJson();
    }
    return data;
  }
}

class BatchTimetable {
  Mon mon;
  Mon tue;

  BatchTimetable({this.mon, this.tue});

  BatchTimetable.fromJson(Map<String, dynamic> json) {
    mon = json['Mon'] != null ? new Mon.fromJson(json['Mon']) : null;
    tue = json['Tue'] != null ? new Mon.fromJson(json['Tue']) : null;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.mon != null) {
      data['Mon'] = this.mon.toJson();
    }
    if (this.tue != null) {
      data['Tue'] = this.tue.toJson();
    }
    return data;
  }
}

class Mon {
  List<String> subject4;
  List<String> subject5;
  List<String> subject6;

  Mon({this.subject4, this.subject5, this.subject6});

  Mon.fromJson(Map<String, dynamic> json) {
    subject4 = json['Subject 4'].cast<String>();
    subject5 = json['Subject 5'].cast<String>();
    subject6 = json['Subject 6'].cast<String>();
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['Subject 4'] = this.subject4;
    data['Subject 5'] = this.subject5;
    data['Subject 6'] = this.subject6;
    return data;
  }
}
...