I’m busy coding a page in my flutter app where I would like it to display a list view from a json file but it keeps giving error [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Unable to load asset: "lib/data/json/foods/foods.json".
The asset does not exist or has empty data.
this is my dart json decoder
class Food {
String name;
double caloriesPer100g;
double fatPer100g;
double ofWhichSaturates;
double carbohydratesPer100g;
double ofWhichSugars;
double proteinPer100g;
double SodiumPer100g;
double ServingSizeGrams;
Food(
this.name,
this.caloriesPer100g,
this.fatPer100g,
this.ofWhichSaturates,
this.carbohydratesPer100g,
this.ofWhichSugars,
this.proteinPer100g,
this.SodiumPer100g,
this.ServingSizeGrams,
);
Food.fromJson(Map<String, dynamic> json)
: name = json['name'],
caloriesPer100g = json["caloriesPer100g"] ?? 0,
fatPer100g = json["fatPer100g"] ?? 0,
ofWhichSaturates = json["ofWhichSaturates"] ?? 0,
carbohydratesPer100g = json["carbohydratesPer100g"] ?? 0,
ofWhichSugars = json["ofWhichSugars"] ?? 0,
proteinPer100g = json["proteinPer100g"] ?? 0,
SodiumPer100g = json["SodiumPer100g"] ?? 0,
ServingSizeGrams = json["ServingSizeGrams"] ?? 0;
}
this is the first 3 elements of the json file
{
"name": "Chobani Greek Yogurt",
"caloriesPer100g": 59,
"fatPer100g": 0,
"ofWhichSaturates": 0,
"carbohydratesPer100g": 4,
"ofWhichSugars": 4,
"proteinPer100g": 10,
"SodiumPer100g": 0.04,
"ServingSizeGrams": 150
},
{
"name": "Oikos Triple Zero Greek Yogurt",
"caloriesPer100g": 83,
"fatPer100g": 0,
"ofWhichSaturates": 0,
"carbohydratesPer100g": 6,
"ofWhichSugars": 6,
"proteinPer100g": 15,
"SodiumPer100g": 0.06,
"ServingSizeGrams": 150
},
{
"name": "Fage Total 0% Greek Yogurt",
"caloriesPer100g": 50,
"fatPer100g": 0,
"ofWhichSaturates": 0,
"carbohydratesPer100g": 4,
"ofWhichSugars": 4,
"proteinPer100g": 10,
"SodiumPer100g": 0.05,
"ServingSizeGrams": 150
},
and this is the file where i plan to show the list of json foods
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:sg_training/data/json/foods/foods.dart';
class AddFood extends StatefulWidget {
@override
_AddFoodState createState() => _AddFoodState();
}
class _AddFoodState extends State<AddFood> {
List<Food> _foods = []; // Move _foods list to _AddFoodState
@override
void initState() {
super.initState();
// Call fetchFoods method when the widget is initialized
fetchFoods().then((foods) {
setState(() {
_foods = foods;
});
});
}
Future<List<Food>> fetchFoods() async {
// Load JSON data from the assets
String jsonString = await DefaultAssetBundle.of(context)
.loadString('lib/data/json/foods/foods.json');
// Decode JSON
var foodsJson = json.decode(jsonString);
// Create a list to store parsed Food objects
List<Food> foods = [];
// Iterate over the JSON array and convert each item to Food object
for (var foodJson in foodsJson) {
foods.add(Food.fromJson(foodJson));
print(foods);
}
return foods;
}
@override
Widget build(BuildContext context) {
fetchFoods().then((value) {
_foods.addAll(value);
});
return MaterialApp(
home: Scaffold(
appBar: AppBar(
centerTitle: true,
leading: BackButton(
onPressed: () {
Navigator.pop(context);
},
),
title: Text("SG training"),
backgroundColor: Colors.blueGrey,
),
body: ListView.builder(
itemBuilder: (context, index) {
return Card(
child: Padding(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_foods[index].name,
style: TextStyle(
fontSize: 15.0, fontWeight: FontWeight.bold),
),
Text(
_foods[index].caloriesPer100g.toString(),
style: TextStyle(color: Colors.grey.shade700),
)
],
),
padding: EdgeInsets.all(15),
),
);
},
itemCount: _foods.length, // Use _foods.length as itemCount
),
),
);
}
}
ive tried two different ways of decoding the json but neither of them work
it should display a list on the screen but it keeps giving an error
i dont know if its the json file the decoder or where i access the decoder but i would be a great help if anyone know how to fix it
2
Answers
You can use a FutureBuilder widget to handle asynchronous operations like fetching data from a JSON file. Here’s how you can refactor your AddFood widget to use FutureBuilder
In this version, the fetchFoods function is moved out of the stateful widget and into the AddFood class. The AddFood widget itself is now a stateless widget. The fetchFoods function now takes a BuildContext as an argument to access the context needed for loading the asset.
The UI is built using a FutureBuilder, which handles the asynchronous fetching of data. It displays a loading spinner while waiting for the data, shows an error message if an error occurs, and displays the list of foods once the data is loaded successfully.
Also If you are Familiar with JsonSerializable package you can rewrite the class in such a way
Make sure you have json_annotation and build_runner dependencies added to your pubspec.yaml file, and run the build command to generate the serialization/deserialization code:
then run:
This is because Flutter cannot detect the file path
You need to specify the path in the pubspac.yaml file
It is also better to put your json in an array because the structure is the same but the count is different