#json #flutter #dart #serializable #mobile-development
Вопрос:
Я пытаюсь проанализировать массив объектов JSON для заполнения представления сетки в Flutter. До сих пор я могу получить только один объект, но не могу обойти весь массив объектов.
Строка JSON: Список объектов рецепта говядины в массиве «говядина».
Мой код:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class SpecificCategoryPage extends StatefulWidget {
late final String category;
SpecificCategoryPage({Key? key, required this.category}) : super(key: key);
@override
_SpecificCategoryPageState createState() => _SpecificCategoryPageState();
}
class _SpecificCategoryPageState extends State<SpecificCategoryPage> {
late Future<Meal> meals;
late List<Widget> mealCards;
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<Meal>(
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(
'TruestnId: ${snapshot.data!.id}. ${snapshot.data!.meal}');
} else {
return Text('${snapshot.error}');
}
// Be default, show a loading spinner.
return CircularProgressIndicator();
},
future: meals,
),
);
}
@override
void initState() {
super.initState();
meals = _fetchMeals();
}
Future<Meal> _fetchMeals() async {
final http.Response mealsData = await http.get(
Uri.parse('https://www.themealdb.com/api/json/v1/1/filter.php?c=Beef'));
if (mealsData.statusCode == 200)
return Meal.fromJson(jsonDecode(mealsData.body));
else
throw Exception('Failed to load meals');
}
class Meal {
final String? id, meal;
Meal({required this.id, required this.meal});
factory Meal.fromJson(Map<String, dynamic> json) {
return Meal(
id: json['meals'][0]['idMeal'], meal: json['meals'][0]['strMeal']);
}
}
Пример пути обхода объекта:
{"meals":[{"strMeal":"Beef and Mustard Pie","strMealThumb":"https://www.themealdb.com/images/media/meals/sytuqu1511553755.jpg","idMeal":"52874"}, {object1}, {object2}]}
Что я получаю:
{«Кукурузная мука»:»Говядина с горчицей Pie»,»strMealThumb»:»https://www.themealdb.com/images/media/meals/sytuqu1511553755.jpg»,»idMeal»:»52874″}
Как мне получить все объекты в массиве и увеличить виджет GridView?
Комментарии:
1. Для дальнейшего анализа Json в dart я рекомендую использовать этот веб-сайт: app.quicktype.io
Ответ №1:
import 'dart:convert';
// First you should create a model to represent a meal
class Meal {
// Place all the meal properties here
final String strMeal;
final String strMealThumb;
final String idMeal;
// Create a constructor that accepts all properties. They can be required or not
Meal({
required this.strMeal,
required this.strMealThumb,
required this.idMeal,
});
// Create a method (or factory constructor to populate the object based on a json input)
factory Meal.fromJson(Map<String, dynamic> json) => Meal(
strMeal: json['strMeal'],
strMealThumb: json['strMealThumb'],
idMeal: json['idMeal'],
);
String toString() {
return 'strMeal: $strMeal, strMealThumb: $strMealThumb, idMeal: $idMeal';
}
}
/// Then you should create another object to represent your response
/// It holds a list of meals that'll be populated by your API response
class YourAPIResponse {
final List<Meal> meals;
YourAPIResponse({required this.meals});
factory YourAPIResponse.fromJson(Map<String, dynamic> json) =>
YourAPIResponse(
meals: List<Meal>.from(
json['meals'].map((meal) => Meal.fromJson(meal)),
),
);
}
void main() {
// Test data: This will be your API response
String jsonString = '{"meals": [{"strMeal": "Beef and Mustard Pie","strMealThumb": "https://www.themealdb.com/images/media/meals/sytuqu1511553755.jpg","idMeal": "52874"}]}';
final apiResponse = YourAPIResponse.fromJson(json.decode(jsonString));
// Your meals list
// You can use this to populate the gridview
print(apiResponse.meals);
}
Комментарии:
1. Работает!
apiResponse.meals
перенастраивает aList
всех объектов питания вместе взятых (i.ie.Future<List<Meal>>
), вместо списка объектов-нелегко перемещатьсяGridView.index()
по индексу.2. Я смог получить его, используя
FutureBuilder<List<Meal>>( builder: (context, snapshot) { if (snapshot.hasData) { return GridView.builder( itemCount: snapshot.data!.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2), itemBuilder: (context, index) { return Text("${snapshot.data![index].id}. ${snapshot.data![index].meal}"); }); } else return Text('Error!'); }, future: meals, )
Ответ №2:
Попробуйте что-нибудь вроде:
...
return jsonDecode(mealsData.body)['meals'].map((meal) => Meal.fromJson(meal)).toList();
...
class Meal {
final String? id, meal;
Meal({required this.id, required this.meal});
factory Meal.fromJson(Map<String, dynamic> json) {
return Meal(
id: json['idMeal'], meal: json['strMeal']);
}
}
Это повторяет приемы пищи в теле вашего ответа и сопоставляет их со списком Meal
s.