簡體   English   中英

如何在flutter中從json獲取數據

[英]How to get data from json in flutter

我正在嘗試訪問我的 JSON 數據,但它返回此錯誤。 我已經操縱了我的 JSON 的結構,但似乎沒有任何修復。 我嘗試將[{:[{}]}]{:[{}]}用於 JSON 格式,但錯誤仍然存​​在。 我想顯示我可以進入容器的數據。

ERROR: RangeError (RangeError (index): Invalid value: Valid value range is empty: 0)

這是我的代碼。

    import 'dart:convert';
    
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:flutter_svg/flutter_svg.dart';
    
    import '../constants (2).dart';
    import '../constants.dart';
    import '../size_config.dart';
    
    class BreakfastCard extends StatefulWidget {
    
        BreakfastCard({
        Key? key,
        this.width = 140,
        this.aspectRetio = 1.02,
      }) : super(key: key);
    
      final double width, aspectRetio;
      @override
      _BreakfastCardState createState() => _BreakfastCardState();
    }
     
    class _BreakfastCardState extends State<BreakfastCard> {
      List breakfast = [];
    
              Future<void> loadBreakfastAsset() async {
              final String loadBreakfastAsset = await rootBundle.loadString('assets/data.json');
              final breakfast = await json.decode(loadBreakfastAsset);
      }
    
    
      @override
      Widget build(BuildContext context) {
        SizeConfig().init(context);
          return Padding(
            padding: EdgeInsets.only(left: getProportionateScreenWidth(20)),
            child: SizedBox(
              width: getProportionateScreenWidth(140),
              child: GestureDetector(
                onTap: (){},
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    AspectRatio(
                      aspectRatio: 1.02,
                      child: Container(
                        padding: EdgeInsets.all(getProportionateScreenWidth(20)),
                        decoration: BoxDecoration(
                          color: kSecondaryColor.withOpacity(0.1),
                          borderRadius: BorderRadius.circular(15),
                        ),
                        child: Hero(
                          tag: breakfast[0]["id"],
                          child: Image.asset(breakfast[0]["images"]),
                        ),
                      ),
                    ),
                    const SizedBox(height: 10),
                    Text(
                      breakfast[0]["title"],
                      style: const TextStyle(color: Colors.black),
                      maxLines: 2,
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text(
                          "${breakfast[0]["calories"]} cal |",
                          style: TextStyle(
                            fontSize: getProportionateScreenWidth(18),
                            fontWeight: FontWeight.bold,
                            color: kPrimaryColor,
                          ),
                        ),
        
                        Text(
                          "${breakfast[0]["time"]} min",
                          style: TextStyle(
                            fontSize: getProportionateScreenWidth(18),
                            fontWeight: FontWeight.w600,
                            color: kPrimaryColor,
                          ),
                        ),
                        InkWell(
                          borderRadius: BorderRadius.circular(50),
                          onTap: () { breakfast[0]["isFavorite"] = !breakfast[0]["isFavorite"];},
                          child: Container(
                            padding: EdgeInsets.all(getProportionateScreenWidth(8)),
                            height: getProportionateScreenWidth(28),
                            width: getProportionateScreenWidth(28),
                            child: SvgPicture.asset(
                              "assets/icons/Heart Icon_2.svg",
                              color: breakfast[0]["images"]
                                  ? const Color(0xFFFF4848)
                                  : const Color(0xFFDBDEE4),
                            ),
                          ),
                        ),
                      ],
                    )
                  ],
                ),
              ),
            ),
          );
  
      }
    }

這是我的 json 文件:

[{
    "items": [{

        "id": "1",
        "rating": "0.0",
        "images": [
            "assets/images/cilantro.png"
        ],
        "title": "Cilantro and Kale Pesto Toast with a Fried Egg",
        "time": "15",
        "description": "Sliced bread is the perfect blank canvas, ready to be loaded up with virtuous ingredients.",
        " rating": "4.8",
        "isFavorite": "false",
        "isPopular": "true",
        "calories": "405",
        "serving": 1,
        "naturalFacts": [
            "405 calories",
            "protein 15g",
            "fat 31g",
            "saturated fat 5.8g",
            "carbohydrates 16g",
            "fiber 1.9g",
            "sodium 331mg",
            "cholesterol 189mg"

        ],
        "ingredients": [
            "¼ cup packed cilantro",
            "1 cup packed kale leaves",
            "¼ cup extra-virgin olive oil",
            "1 tablespoon white balsamic vinegar",
            "2 tablespoons hulled hemp seeds*",
            "salt",
            "Freshly ground pepper",
            "1 large slice of whole-wheat toast",
            "2 tablespoons unflavored whole-milk Greek yogurt",
            "1 fried egg"
        ],
        "procedure": [
            "Whirl the cilantro, kale leaves, extra-virgin olive oil, white balsamic vinegar, and hemp seeds* until fairly smooth, scraping inside of bowl.",
            "Season with sea salt and freshly ground pepper. Smear a large slice of whole-wheat toast with the yogurt, then with some pesto.",
            "Top with a fried egg and more salt and pepper."
        ]

    }]
}]

這是模型

import 'package:flutter/material.dart';

class Breakfast {
  final int id, time, serving;
  final String title, description, calories;
  final List <String> procedure;
  final List <String> ingredients;
  final List <String> naturalFacts;
  final List<String> images;
  final double rating;
  bool isFavorite, isPopular;

  Breakfast({
    required this.id,
    required this.images,
    this.rating = 0.0,
    this.isFavorite = false,
    this.isPopular = false,
    required this.title,
    required this.time,
    required this.description,
    required this.ingredients,
    required this.procedure,
    required this.naturalFacts,
    required this.calories,
    required this.serving,
  });

    factory Breakfast.fromJson(Map<String, dynamic> parsedJson) {
    var procedureFromJson  = parsedJson['procedure'];
    var ingredientsFromJson  = parsedJson['ingredients'];
    var naturalFactsFromJson  = parsedJson['naturalFacts'];
    var imagesFromJson  = parsedJson['images'];
    
    //print(streetsFromJson.runtimeType);
    // List<String> streetsList = new List<String>.from(streetsFromJson);
    List<String> ingredientsList = ingredientsFromJson.cast<String>();
    List<String> procedureList = procedureFromJson.cast<String>();
    List<String> imagesList = imagesFromJson.cast<String>();

    return new Breakfast(
      calories: parsedJson['calories'],
      time: parsedJson['time'],
      title: parsedJson['title'],
      description: parsedJson['description'],
      naturalFacts: parsedJson['naturalFacts'],
      serving: parsedJson['serving'],
      id: parsedJson['id'],

      procedure: procedureList,
      ingredients: ingredientsList,
      images: imagesList,
    );
  }
}

當您根據您傳遞的索引調用長度不足的列表時會發生這種情況,即早餐 [0]

你已經創建了一個 Future,但你需要使用 FutureBuilder 來調用它,這樣你的數據就可以傳遞到你的列表中,並且可以在這里訪問早餐 [0]

首先,雖然我們不需要[]JSON數據的外側。

第二個問題來自數據類型。 關於 JSON 建模。 如果仔細觀察, id在 JSON 上是 String 而在模型類上是int 在 JSON 上將id轉換為 int,

"id": 1,一樣,其他字段也一樣,檢查數據類型並基於它創建模型。

在此處輸入圖片說明

第三,它需要使用FutureBuilder來加載資產的 JSON 並解析它。

它會像

  Future<List<Breakfast>> loadBreakfastAsset() async {
    final String _loadBreakfastAsset =
        await rootBundle.loadString('json/bg.json');
    final jsonString = await json.decode(_loadBreakfastAsset)["items"] as List;
    final breakfastList = jsonString.map((e) => Breakfast.fromJson(e)).toList();

    return breakfastList;
  }

你按照我的說明去做。

我正在分享經過測試的代碼片段,您需要檢查並應用到所有人。


class Breakfast {
  final int id;
  final int time;
  final int serving;
  final String title;

  final List<String> procedure;

  Breakfast({
    required this.id,
    required this.time,
    required this.serving,
    required this.title,
    required this.procedure,
  });

  factory Breakfast.fromJson(Map<String, dynamic> parsedJson) {
    var procedureFromJson = parsedJson['procedure'];

    List<String> procedureList = procedureFromJson.cast<String>();

    return Breakfast(
      title: parsedJson['title'],
      serving: parsedJson['serving'],
      id: parsedJson['id'],
      time: parsedJson['time'],
      procedure: procedureList,
    );
  }
}

class _BreakfastCardState extends State<BreakfastCard> {
  Future<List<Breakfast>> loadBreakfastAsset() async {
    final String _loadBreakfastAsset =
        await rootBundle.loadString('json/bg.json');
    final jsonString = await json.decode(_loadBreakfastAsset)["items"] as List;
    final breakfastList = jsonString.map((e) => Breakfast.fromJson(e)).toList();

    return breakfastList;
  }

  @override
  Widget build(BuildContext context) {
    // SizeConfig().init(context);
    return FutureBuilder<List<Breakfast>>(
        future: loadBreakfastAsset(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const CircularProgressIndicator();
          } else if (snapshot.hasError) {
            return Text("Got ERR :${snapshot.error}");
          } else if (snapshot.hasData) {
            final List<Breakfast> breakfast = snapshot.data!;
            return Padding(
              padding: const EdgeInsets.only(left: (20)),
              child: SizedBox(
                // width: getProportionateScreenWidth(140),
                width: 100,
                height: 200,
                child: GestureDetector(
                  onTap: () {},
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      AspectRatio(
                        aspectRatio: 1.02,
                        child: Container(
                          // padding: EdgeInsets.all(getProportionateScreenWidth(20)),
                          decoration: BoxDecoration(
                            // color: kSecondaryColor.withOpacity(0.1),
                            borderRadius: BorderRadius.circular(15),
                          ),
                          // child: Hero(
                          //   tag: breakfast[0]["id"],
                          //   child: Image.asset(breakfast[0]["images"]),
                          // ),
                        ),
                      ),
                      const SizedBox(height: 10),
                      Text(
                        breakfast[0].title,
                        style: const TextStyle(color: Colors.black),
                        maxLines: 2,
                      ),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          // Text(
                          //   "${breakfast[0].calories} cal |",
                          //   style: TextStyle(
                          //     // fontSize: getProportionateScreenWidth(18),
                          //     fontWeight: FontWeight.bold,
                          //     // color: kPrimaryColor,
                          //   ),
                          // ),
                          Text(
                            "${breakfast[0].time} min",
                            style: TextStyle(
                              // fontSize: getProportionateScreenWidth(18),
                              fontWeight: FontWeight.w600,
                              // color: kPrimaryColor,
                            ),
                          ),
                          InkWell(
                            borderRadius: BorderRadius.circular(50),
                            onTap: () {
                              // breakfast[0].isFavorite =
                              //     !breakfast[0].isFavorite;
                            },
                            child: Container(
                                padding: EdgeInsets.all((8)), child: Text("A")),
                          ),
                        ],
                      )
                    ],
                  ),
                ),
              ),
            );
          }
          return Text("...");
        });
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM