#json #flutter #dart
Вопрос:
// ignore_for_file: prefer_const_constructors, avoid_unnecessary_containers, prefer_const_literals_to_create_immutables, import_of_legacy_library_into_null_safe, non_constant_identifier_names, unused_field, avoid_print import 'dart:convert'; import 'package:dropdownfield/dropdownfield.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class FoodWidget extends StatefulWidget { const FoodWidget({Key? key}) : super(key: key); @override _FoodWidgetState createState() =gt; _FoodWidgetState(); } class _FoodWidgetState extends Statelt;FoodWidgetgt; { @override void initState() { fetchFood(); super.initState(); } String? food_id; List food = []; Futurelt;voidgt; fetchFood() async { final String response = await rootBundle.loadString('assets/list_food.json'); final data = await json.decode(response); print(data); setState(() { food = data["food"]; }); } @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(15.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: lt;Widgetgt;[ DropDownField( onValueChanged: (dynamic value) { food_id = value; }, value: food_id, required: false, labelText: 'Search food', items: food, ), ]), ); } }
а это файл JSON. Я хочу, чтобы в раскрывающемся списке были только имена, но я не могу этого сделать. В функции setState я действительно не знаю, как это выразить.
{ "food": [ { "id": 1, "name": "coca-cola", "calories": 120 }, { "id": 2, "name": "egg", "calories": 80 }, { "id": 3, "name": "rice", "calories": 100 } ] }
Я попытался распечатать(данные), чтобы проверить вывод. Все это исходит из доменного имени, но я хочу использовать его внутри. И я действительно не знаю, как это сделать.
пс. Я действительно буду признателен за ответы и предложения.
Ответ №1:
вам просто нужно будет сопоставить данные, чтобы получить только их название :
Futurelt;voidgt; fetchFood() async { final String response = await rootBundle.loadString('assets/list_food.json'); final data = await json.decode(response); print(data); setState(() { food = data["food"].map((e)=gt;e['name']).toList(); }); }
Там, получив список продуктов, вы сопоставляете каждый элемент, чтобы получить только название продукта, которое вам нужно.
В качестве примечания
Я бы рекомендовал вам в будущем создать такую модель, как :
class Food { Food({ this.id, this.name, this.calories, }); int id; String name; int calories; factory Food.fromJson(Maplt;String, dynamicgt; json) =gt; Food( id: json["id"], name: json["name"], calories: json["calories"], ); Maplt;String, dynamicgt; toJson() =gt; { "id": id, "name": name, "calories": calories, }; }
Таким образом, у вас есть строгая типизация Listlt;Foodgt; food
, и вы можете получить доступ к параметрам в типобезопасном режиме.
Ответ №2:
Вам нужно создать класс продуктов питания
class Food { String? id; String? name; String? calories; Food({ this.id, this.name, this.calories, }); Maplt;String, dynamicgt; toMap() { return { 'id': id, 'name': name, 'calories': calories, }; } factory Food.fromMap(Maplt;String, dynamicgt; map) { return Food( id: map['id'], name: map['name'], calories: map['calories'], ); } String toJson() =gt; json.encode(toMap()); factory Food.fromJson(String source) =gt; Food.fromMap(json.decode(source)); }
Полный код здесь:
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class FoodWidget extends StatefulWidget { const FoodWidget({Key? key}) : super(key: key); @override _FoodWidgetState createState() =gt; _FoodWidgetState(); } class _FoodWidgetState extends Statelt;FoodWidgetgt; { @override void initState() { fetchFood(); super.initState(); } String? food_id; Food? selected_food ; Listlt;Foodgt; food = []; Futurelt;voidgt; fetchFood() async { final String response = await rootBundle.loadString('assets/list_food.json'); final data = await json.decode(response) as List; print(data); setState(() { food = data.map((e) =gt; Food.fromJson(e)).toList(); }); } @override Widget build(BuildContext context) { return Container( padding:const EdgeInsets.all(15.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: lt;Widgetgt;[ DropdownButtonlt;Foodgt;( focusColor: Colors.white, value: selected_food, //elevation: 5, style: const TextStyle(color: Colors.white), iconEnabledColor: Colors.black, underline: const SizedBox.shrink(), items: food.maplt;DropdownMenuItemlt;Foodgt;gt;( (Food value) { return DropdownMenuItemlt;Foodgt;( value: value, child: Text( value.name!, style: const TextStyle(color: Colors.black), ), ); }).toList(), hint: const Text( "Select Shop Category", style: TextStyle( color: Colors.black38, ), ), onChanged: (Food? value) { setState(() { selected_food= value!; }); }, ), ]), ); } } class Food { String? id; String? name; String? calories; Food({ this.id, this.name, this.calories, }); Maplt;String, dynamicgt; toMap() { return { 'id': id, 'name': name, 'calories': calories, }; } factory Food.fromMap(Maplt;String, dynamicgt; map) { return Food( id: map['id'], name: map['name'], calories: map['calories'], ); } String toJson() =gt; json.encode(toMap()); factory Food.fromJson(String source) =gt; Food.fromMap(json.decode(source)); }