# #json #firebase #flutter #dart
Вопрос:
Ниже приведен пример QueryDocumentSnapshot под названием «неделя», который я получаю из Firestore с помощью StreamBuilder. Я ищу способ отображения этих более или менее сложных данных в чем-то вроде виджета-карты с информацией из каждого снимка в моем проекте Flutter.
{
"days":{
"3": {
"activities": {
"1628658343103": {
"query": "I am watering the plants",
"finished": false,
"params": [
{
"pronounsDefinite": "I"
},
{
"verbsHelpPresent": "am"
},
{
"verbsGerund": "watering"
},
{
"articles": "the"
},
{
"nouns": "plant"
}
],
"intent": "gHomesAndBuildingsGardensAC",
"duration": 3
},
"1628673512954": {
"query": "I am cutting the bushes",
"finished": false,
"params": [
{
"pronounsDefinite": "I"
},
{
"verbsHelpPresent": "am"
},
{
"verbsGerund": "cutting"
},
{
"articles": "the"
},
{
"nouns": "bush"
}
],
"intent": "gHomesAndBuildingsGardensAC",
"duration": 3
},
"1628673476549": {
"query": "I work in the garden",
"finished": false,
"params": [
{
"pronounsDefinite": "I"
},
{
"verbsInfinitiv": "work"
},
{
"prepositions": "in"
},
{
"articles": "the"
},
{
"nouns": "garden"
}],
"intent": "gHomesAndBuildingsGardensAC",
"duration": 4
}
}
},
"4": {
"activities": {
"1628658343104": {
"query": "I am watering the plants",
"finished": false,
"params": [
{
"pronounsDefinite": "I"
},
{
"verbsHelpPresent": "am"
},
{
"verbsGerund": "watering"
},
{
"articles": "the"
},
{
"nouns": "plant"
}
],
"intent": "gHomesAndBuildingsGardensAC",
"duration": 3
},
"1628673512956": {
"query": "I am cutting the bushes",
"finished": false,
"params": [
{
"pronounsDefinite": "I"
},
{
"verbsHelpPresent": "am"
},
{
"verbsGerund": "cutting"
},
{
"articles": "the"
},
{
"nouns": "bush"
}
],
"intent": "gHomesAndBuildingsGardensAC",
"duration": 3
},
"1628673476559": {
"query": "I work in the garden",
"finished": false,
"params": [
{
"pronounsDefinite": "I"
},
{
"verbsInfinitiv": "work"
},
{
"prepositions": "in"
},
{
"articles": "the"
},
{
"nouns": "garden"
}],
"intent": "gHomesAndBuildingsGardensAC",
"duration": 3
}
}
}
}
}
Вот в чем проблема:
У меня есть метод ListView.builder, который создает виджет для каждого документа моментального снимка, как описано выше.
Цифровые клавиши в разделе «действия» являются метками времени. Я могу отобразить некоторый текст, используя это:
...
Text(
week['days']['3']['activities']['1628658343103']['query'].toString()
), //Which displays: "I am watering the plants"
Но таким образом, я должен был бы знать каждую метку времени и называть ее таким образом с точным номером, который, очевидно, не работает.
Как я могу использовать что-то вроде «forEach ()» для перебора всех существующих записей в действиях?
Я также создал класс модели для этого, используя https://app.quicktype.io но затем он создает исключение FormatException, потому что я пытаюсь вставить в класс QueryDocumentSnapshot в тот момент, когда я пытаюсь это сделать:
Widget buildCard(BuildContext context, DocumentSnapshot week) {
final dataFromWeek = dataFromWeekFromJson(week.toString());
return new Container(.....);
//In this Container, all the text from json should be displayed
}
а вот мой класс модели, который я получил из инструмента быстрого ввода JSON.
// To parse this JSON data, do
//
// final dataFromWeek = dataFromWeekFromJson(jsonString);
import 'dart:convert';
DataFromWeek dataFromWeekFromJson(String str) =>
DataFromWeek.fromJson(json.decode(str));
String dataFromWeekToJson(DataFromWeek data) => json.encode(data.toJson());
class DataFromWeek {
DataFromWeek({
this.days,
});
Map<String, Day> days;
factory DataFromWeek.fromJson(Map<String, dynamic> json) => DataFromWeek(
days: Map.from(json["days"])
.map((k, v) => MapEntry<String, Day>(k, Day.fromJson(v))),
);
Map<String, dynamic> toJson() => {
"days": Map.from(days)
.map((k, v) => MapEntry<String, dynamic>(k, v.toJson())),
};
}
class Day {
Day({
this.activities,
});
Map<String, Activity> activities;
factory Day.fromJson(Map<String, dynamic> json) => Day(
activities: Map.from(json["activities"])
.map((k, v) => MapEntry<String, Activity>(k, Activity.fromJson(v))),
);
Map<String, dynamic> toJson() => {
"activities": Map.from(activities)
.map((k, v) => MapEntry<String, dynamic>(k, v.toJson())),
};
}
class Activity {
Activity({
this.query,
this.finished,
this.params,
this.intent,
this.duration,
});
String query;
bool finished;
List<Param> params;
String intent;
int duration;
factory Activity.fromJson(Map<String, dynamic> json) => Activity(
query: json["query"],
finished: json["finished"],
params: List<Param>.from(json["params"].map((x) => Param.fromJson(x))),
intent: json["intent"],
duration: json["duration"],
);
Map<String, dynamic> toJson() => {
"query": query,
"finished": finished,
"params": List<dynamic>.from(params.map((x) => x.toJson())),
"intent": intent,
"duration": duration,
};
}
class Param {
Param({
this.pronounsDefinite,
this.verbsHelpPresent,
this.verbsGerund,
this.articles,
this.nouns,
this.verbsInfinitiv,
this.prepositions,
});
String pronounsDefinite;
String verbsHelpPresent;
String verbsGerund;
String articles;
String nouns;
String verbsInfinitiv;
String prepositions;
factory Param.fromJson(Map<String, dynamic> json) => Param(
pronounsDefinite:
json["pronounsDefinite"] == null ? null : json["pronounsDefinite"],
verbsHelpPresent:
json["verbsHelpPresent"] == null ? null : json["verbsHelpPresent"],
verbsGerund: json["verbsGerund"] == null ? null : json["verbsGerund"],
articles: json["articles"] == null ? null : json["articles"],
nouns: json["nouns"] == null ? null : json["nouns"],
verbsInfinitiv:
json["verbsInfinitiv"] == null ? null : json["verbsInfinitiv"],
prepositions:
json["prepositions"] == null ? null : json["prepositions"],
);
Map<String, dynamic> toJson() => {
"pronounsDefinite": pronounsDefinite == null ? null : pronounsDefinite,
"verbsHelpPresent": verbsHelpPresent == null ? null : verbsHelpPresent,
"verbsGerund": verbsGerund == null ? null : verbsGerund,
"articles": articles == null ? null : articles,
"nouns": nouns == null ? null : nouns,
"verbsInfinitiv": verbsInfinitiv == null ? null : verbsInfinitiv,
"prepositions": prepositions == null ? null : prepositions,
};
}
На самом деле я не хочу отображать «параметры», но было бы здорово, если бы была некоторая гибкость, поэтому я пытаюсь использовать класс модели для отображения данных моментального снимка в «Карточке-виджете».
Ответ №1:
Вы хотите получить все действия за определенный день, а затем просмотреть их и создать карточку.
Во-первых, это то, как вы должны структурировать свои данные.
«дни» (коллекция) -> «3» (документ) ->> «мероприятия» (вложенная коллекция в документе 3)
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<QuerySnapshot<Activity>>(
// below will return all the activities for under doc('3')
stream: FirebaseFirestore.instance
.collection("days")
.doc('3')
.collection("activities")
// NB: I used your Activity Model
.withConverter<Activity>(
fromFirestore: (snapshot, _) =>
Activity.fromJson(snapshot.data()),
toFirestore: (data, _) => data.toJson(),
)
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot<Activity>> snapshot) {
if (snapshot.hasError) return Text('Something went wrong');
if (snapshot.connectionState == ConnectionState.waiting)
return CircularProgressIndicator();
// you can then loop through query and build the card;
List<Activity> _activities =
snapshot.data.docs.map((e) => e.data()).toList();
return ListView.builder(
itemCount: _activities.length,
itemBuilder: (context, i) {
// you can return a card here.
return ListTile(
title: Text(_activities[i].query),
);
},
);
},
),
);
}