Put JSON Data in Flutter Stacked Chart - json

I have try to put my JSON data in flutter Stacked Chart.
I already work on simple charts using JSON Data like bar, column, pie, Doughnut charts etc.
I have refer
stacked-column-chart(syncfusion_flutter_charts),
Grouped Bar Chart(charts_flutter)
Stack Overflow Que-Ans
below like my API response/JSON String
[{
"name": "ABC",
"subject": [{
"name": "Math",
"marks": "54"
},
{
"name": "Physics",
"marks": "65"
}
]
},
{
"name": "PQR",
"subject": [{
"name": "Chemistry",
"marks": "53"
},
{
"name": "Biology",
"marks": "22"
},
{
"name": "English",
"marks": "7 "
},
{
"name": "Math",
"marks": "12"
}
]
}, {
"name": "JKL",
"subject": [{
"name": "Chemistry",
"marks": "53"
},
{
"name": "Biology",
"marks": "22"
},
{
"name": "English",
"marks": "79 "
},
{
"name": "Math",
"marks": "12"
},
{
"name": "Physics",
"marks": "72"
}
]
}
]
Or I want below type of graph using JSON Data
Note: Suggest me my JSON string is wrong, you can create your own JSON data and display the output

Using charts_flutter. Please customize it for your usecase its a bare minimum implementation to validate that its working for your json.
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
import 'dart:convert';
class StackedBarChart extends StatelessWidget {
final bool animate;
StackedBarChart({this.animate = false});
// EXCLUDE_FROM_GALLERY_DOCS_END
#override
Widget build(BuildContext context) {
String jsonString = '[{"name":"ABC","subject":[{"name":"Math","marks":"54"},{"name":"Physics","marks":"65"}]},{"name":"PQR","subject":[{"name":"Chemistry","marks":"53"},{"name":"Biology","marks":"22"},{"name":"English","marks":"7 "},{"name":"Math","marks":"12"}]},{"name":"JKL","subject":[{"name":"Chemistry","marks":"53"},{"name":"Biology","marks":"22"},{"name":"English","marks":"79 "},{"name":"Math","marks":"12"},{"name":"Physics","marks":"72"}]}]';
final studentMarks = studentMarksFromJson(jsonString);
var subjects = <Subject?>{};
var subjectsDist = <Subject?>{};
int c=0;
for (var stdnt in studentMarks) {
for (var subjs in stdnt.subject) {
if (!subjectsDist.where((element) => element?.name==subjs.name).isNotEmpty) {
subjs.sno=c++;
subjectsDist.add(subjs);
}
}
}
print(subjectsDist.length);
List<List<OrdinalMarks>> SubjectData = [];
for (var subjs in subjectsDist) {
List<OrdinalMarks> marksData = [];
for (var stdnt in studentMarks) {
if (stdnt.subject
.where((element) => element.name == subjs?.name).isNotEmpty) {
var temp = stdnt.subject
.where((element) => element.name == subjs?.name)
.first;
marksData.add(OrdinalMarks(temp.name, int.parse(temp.marks),stdnt.name));
} else {
marksData.add(OrdinalMarks(subjs!.name, 0,stdnt.name));
}
}
SubjectData.add(marksData);
}
var palettes = charts.MaterialPalette.getOrderedPalettes(subjectsDist.length+2);
int cnt=0;
List<charts.Series<OrdinalMarks, String>> chartData = [
];
for(var d in SubjectData)
{
chartData.add(new charts.Series<OrdinalMarks, String>(
id: d.first.subjectName,
domainFn: (OrdinalMarks m, _) => m.studentName,
measureFn: (OrdinalMarks m, _) => m.marks,
data: d,
fillColorFn: ( subj, _) {
// print(subj.subjectName+": subj.subjectName :" + pallets[subj.subjectName].toString()??charts.MaterialPalette.blue.shadeDefault.toString());
return palettes.elementAt( subjectsDist.where((element) => element?.name==subj.subjectName).first?.sno??0 ).shadeDefault; //pallets[subj.subjectName]??charts.MaterialPalette.blue.shadeDefault;
},
colorFn: ( subj, _) {
// print(subj.subjectName+": subj.subjectName :" + pallets[subj.subjectName].toString()??charts.MaterialPalette.blue.shadeDefault.toString());
return palettes.elementAt(subjectsDist.where((element) => element?.name==subj.subjectName).first?.sno??0).shadeDefault;
},
));
}
return Scaffold(
// Use Obx(()=> to update Text() whenever count is changed.
appBar: AppBar(title: Text("Chart")),
// Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context
body:new charts.BarChart(
chartData,
animate: animate,
behaviors: [new charts.SeriesLegend(showMeasures: true)],
animationDuration: Duration(seconds: 3),
));
}
}
/// Sample ordinal data type.
class OrdinalMarks {
final String subjectName;
final int marks;
final String studentName;
OrdinalMarks(this.subjectName, this.marks,this.studentName);
}
List<StudentMarks> studentMarksFromJson(String str) => List<StudentMarks>.from(json.decode(str).map((x) => StudentMarks.fromJson(x)));
String studentMarksToJson(List<StudentMarks> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class StudentMarks {
StudentMarks({
required this.name,
required this.subject,
});
String name;
List<Subject> subject;
factory StudentMarks.fromJson(Map<String, dynamic> json) => StudentMarks(
name: json["name"],
subject: List<Subject>.from(json["subject"].map((x) => Subject.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"name": name,
"subject": List<dynamic>.from(subject.map((x) => x.toJson())),
};
}
class Subject {
Subject({
required this.name,
required this.marks,
});
String name;
String marks;
int? sno;
factory Subject.fromJson(Map<String, dynamic> json) => Subject(
name: json["name"],
marks: json["marks"],
);
Map<String, dynamic> toJson() => {
"name": name,
"marks": marks,
};
}

Related

Parse JSON to Dart with nested List objects

How to parse from JSON to Dart object including 2 nested classes inside of properties oof the class, Lists?
A JSON object Video that contains a list of Question objects.
Question objects contains a list of Ans objects.
{
"id": 1,
"videoUrl": "https://assets.mixkit.co/videos/preview/mixkit-machinery-of-a-very-close-watch-3673-large.mp4",
"questions": [
{
"id": "0-903669-72-2",
"type": "mc",
"body": "Understand reality truth food agency artist.",
"correctAnswerId": "0-259-85157-4",
"ans": [
{
"id": "0-259-85157-4",
"body": "Play."
},
{
"id": "0-694-71578-6",
"body": "Whose trip."
},
{
"id": "0-13-124278-4",
"body": "Of figure why."
},
{
"id": "0-8169-6726-1",
"body": "Station culture green."
}
]
},
{
"id": "1-872297-31-5",
"type": "mc",
"body": "Especially resource benefit beautiful world six.",
"correctAnswerId": "1-61799-113-9",
"ans": [
{
"id": "0-384-69655-4",
"body": "Form."
},
{
"id": "0-89336-975-6",
"body": "Call."
},
{
"id": "1-61799-113-9",
"body": "Money three young."
},
{
"id": "1-60950-585-9",
"body": "Three threat back."
}
]
},
{
"id": "0-297-13339-X",
"type": "mc",
"body": "Of smile coach second firm ahead.",
"correctAnswerId": "1-916803-19-9",
"ans": [
{
"id": "0-15-955520-5",
"body": "Add old catch."
},
{
"id": "0-606-65499-2",
"body": "Well great task."
},
{
"id": "0-7364-1942-X",
"body": "Arrive resource speech kid."
},
{
"id": "1-916803-19-9",
"body": "Reach brother book."
}
]
},
{
"id": "0-254-52906-2",
"type": "ms",
"correctAnswers": [
"1-146-90255-7",
"0-17-470673-1"
],
"body": "Particularly affect but necessary.",
"ans": [
{
"id": "0-17-278557-X",
"body": "Response bill."
},
{
"id": "0-17-470673-1",
"body": "Attack sister interview."
},
{
"id": "0-16-027096-0",
"body": "Design garden."
},
{
"id": "1-146-90255-7",
"body": "Short break."
}
]
},
{
"id": "0-926285-49-1",
"type": "ms",
"correctAnswers": [
"0-554-50421-9",
"0-294-02768-8"
],
"body": "Experience family training.",
"ans": [
{
"id": "0-8260-5153-7",
"body": "Mouth exist kid."
},
{
"id": "0-294-02768-8",
"body": "Agreement factor."
},
{
"id": "0-554-50421-9",
"body": "Down race professional show."
},
{
"id": "1-124-45547-7",
"body": "Most such onto strategy."
}
]
}
]
}
I tried using this tool after failing to properly do this myself.
https://javiercbk.github.io/json_to_dart/
This is the class definitions I got(I changed some things because of VSCode suggestions).
class Video {
int? id;
String? videoUrl;
List<Question>? questions;
Video({this.id, this.videoUrl, this.questions});
Video.fromJson(Map<String, dynamic> json) {
id = json['id'];
videoUrl = json['videoUrl'];
if (json['questions'] != null) {
questions = <Question>[];
json['questions'].forEach((v) {
questions!.add(Question.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['videoUrl'] = videoUrl;
if (this.questions != null) {
data['questions'] = questions!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Question {
String? id;
String? type;
String? body;
String? correctAnswerId;
List<Ans>? ans;
List<String>? correctAnswers;
Question(
{this.id,
this.type,
this.body,
this.correctAnswerId,
this.ans,
this.correctAnswers});
Question.fromJson(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
body = json['body'];
correctAnswerId = json['correctAnswerId'];
if (json['ans'] != null) {
ans = <Ans>[];
json['ans'].forEach((v) {
ans!.add(Ans.fromJson(v));
});
}
correctAnswers = json['correctAnswers'].cast<String>();
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['type'] = type;
data['body'] = body;
data['correctAnswerId'] = correctAnswerId;
if (ans != null) {
data['ans'] = ans!.map((v) => v.toJson()).toList();
}
data['correctAnswers'] = correctAnswers;
return data;
}
}
class Ans {
String? id;
String? body;
Ans({this.id, this.body});
Ans.fromJson(Map<String, dynamic> json) {
id = json['id'];
body = json['body'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['body'] = body;
return data;
}
}
I load the JSON like this.
getVid() async {
final String response = await rootBundle.loadString('assets/videos.json');
final data = await json.decode(response)['videos'];
List<Video> vids = List<Video>.from(data.map((x) => Video.fromJson(x)));
}
But end up with this error message inside of the console.
Uncaught (in promise) Error: NoSuchMethodError: 'cast'
Dynamic call of null.
Receiver: null
Arguments: []
Your help is greatly appreciated!
This line of code correctAnswers = json['correctAnswers'].cast<String>(); is causing error, as it is not able to cast it as list of string
Try using List.from() or map() or List.of()methods
correctAnswers = List<String>.from(json['correctAnswers']);
Or
correctAnswers = json['correctAnswers'].map((answer) => answer.toString()).toList();
Or
correctAnswers = List<String>.of(json['correctAnswers']);

Parse Array in Object in Array in Dart / Flutter

I have a REST Service I like to consume, but I do not know how to parse that JSON to an Object.
My JSON looks like that:
[
{
"types": {
"KEYWORD": "STRING"
},
"displaynames": {
"KEYWORD": "Keyword"
},
"rows": [
{
"KEYWORD": "Test 1"
},
{
"KEYWORD": "Test 2"
}
]
}
]
That is my object I created from that:
import 'dart:convert';
List<Todo> welcomeFromJson(String str) =>
List<Todo>.from(json.decode(str).map((x) => Todo.fromJson(x)));
String welcomeToJson(List<Todo> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Todo {
Todo({
required this.types,
required this.displaynames,
required this.rows,
});
Displaynames types;
Displaynames displaynames;
List<Displaynames> rows;
factory Todo.fromJson(Map<String, dynamic> json) => Todo(
types: Displaynames.fromJson(json["types"]),
displaynames: Displaynames.fromJson(json["displaynames"]),
rows: List<Displaynames>.from(
json["rows"].map((x) => Displaynames.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"types": types.toJson(),
"displaynames": displaynames.toJson(),
"rows": List<dynamic>.from(rows.map((x) => x.toJson())),
};
}
class Displaynames {
Displaynames({
required this.keyword,
});
String keyword;
factory Displaynames.fromJson(Map<String, dynamic> json) => Displaynames(
keyword: json["KEYWORD"],
);
Map<String, dynamic> toJson() => {
"KEYWORD": keyword,
};
}
I try Loading the JSON and Display like that by using the pull_to_refresh Package.
import 'package:flutter/material.dart';
import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';
import 'dart:convert';
import 'package:user_portal/model/todo.dart';
class TodoRoute extends StatefulWidget {
const TodoRoute({super.key});
#override
State<TodoRoute> createState() => _TodoRouteState();
}
class _TodoRouteState extends State<TodoRoute> {
late List<Todo> todoList = [];
final RefreshController refreshController =
RefreshController(initialRefresh: true);
Future<bool> fetchTodo() async {
const String jsonstr =
'[ { "types": { "KEYWORD": "STRING" }, "displaynames": { "KEYWORD": "Keyword" }, "rows": [ { "KEYWORD": "Test 1" }, { "KEYWORD": "Test 2" } ] }]';
todoList = (json.decode(jsonstr) as List)
.map((data) => Todo.fromJson(data))
.toList();
setState(() {});
return true;
}
#override
Widget build(context) {
return Scaffold(
appBar: AppBar(
title: const Text('Todo'),
),
body: SmartRefresher(
controller: refreshController,
enablePullUp: true,
onRefresh: () async {
final result = await fetchTodo();
if (result) {
refreshController.refreshCompleted();
} else {
refreshController.refreshFailed();
}
},
onLoading: () async {
final result = await fetchTodo();
if (result) {
refreshController.loadComplete();
} else {
refreshController.loadFailed();
}
},
child: ListView.separated(
scrollDirection: Axis.vertical,
itemCount: todoList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(todoList[0].rows[index].keyword),
);
},
separatorBuilder: (context, index) => const Divider(),
),
),
);
}
}
But the Only Item I get is the Test 1 Item not the Test 2 Item and I do not know where to look further for that Problem.
try this way it's so easy...
add this method in your TOdo model
static List< Todo > fromList(json) {
List< Todo > tempList = [];
try {
json.forEach((element) {
tempList.add(Todo.fromJson(element));
});
return tempList;
} catch (e) {
return tempList;
}
}
change this function
Future<bool> fetchTodo() async {
const String jsonstr =
'[ { "types": { "KEYWORD": "STRING" },
"displaynames": { "KEYWORD": "Keyword" }, "rows": [ {
"KEYWORD": "Test 1" }, { "KEYWORD": "Test 2" }
]
}]';
Map data = json.decode(jsonstr);
todoList = Todo.fromList(data);
setState(() {});
return true;
}
Change your fetchTodo() to this:
Future<bool> fetchTodo() async {
const String jsonstr =
'[ { "types": { "KEYWORD": "STRING" }, "displaynames": { "KEYWORD": "Keyword" }, "rows": [ { "KEYWORD": "Test 1" }, { "KEYWORD": "Test 2" } ] }]';
todoList = welcomeFromJson(jsonstr);//<--- add this
setState(() {});
return true;
}
also change this in asdas class:
factory Todo.fromJson(Map<String, dynamic> json) => Todo(
types: Displaynames.fromJson(json["types"]),
displaynames: Displaynames.fromJson(json["displaynames"]),
rows: json["rows"] != null ? (json["rows"] as List).map((x) => Displaynames.fromJson(x)).toList():[],

Access up to the "model" key parameter in my listview builder for the provided json format in flutter

I want to access up to the "model" key parameter in my listview builder for the provided json format in flutter but I don't know how can I access them
I want to access the child object model
What the json will look like:
[
{
"vehicle": "roadways",
"id": "10000",
"category": {
"500": {
"id": "500",
"name": "Bike",
"icon": "http://example.com/bike.jpg",
"model": [
{
"id": "510",
"name": "Harley"
},
{
"id": "520",
"name": "Kawasaki"
}
]
},
"50": {
"id": "50",
"name": "Car",
"icon": "http://example.com/car.jpg",
}
},
},
{
"vehicle": "waterways",
"id": "20000",
"category": {
"600": {
"id": "600",
"name": "Ship",
"icon": "http://example.com/ship.jpg",
"model": [
{
"id": "610",
"name": "model_1"
},
{
"id": "520",
"name": "model_2"
}
]
},
"700": {
"id": "700",
"name": "model_3",
"icon": "http://example.com/car.jpg",
}
},
}
]
var data = jsonDecode("yourJosnString");
ListView.builder(
itemCount: data.length,
itemBuilder: (context, i) {
var data1 = data[i]["category"];
String firstKey = data1.keys.first;
var model = data1[firstKey];
return Column(
children: [
for (i = 0; i < model.length; i++) ...[
Text(
model["name"],
)
]
],
);
},
),
you should first make an object for this json, like this:
class Vehicle {
final String name;
final VehicleCategory category;
Vehicle({#required this.name, #required this.category});
static List<Vehicle> fromJson(List _list) {
List<Vehicle> result = [];
for (var item in _list) {
var address = Vehicle(
name: item['id'] as String,
category: VehicleCategory.fromJson(
item['category']['500'] as Map<String, Object> ?? {}),
);
result.add(address);
}
return result;
}
}
class VehicleCategory {
final String name;
final String icon;
final List<VehicleModel> model;
VehicleCategory(
{#required this.name, #required this.icon, #required this.model});
static VehicleCategory fromJson(Map<String, Object> _json) {
return VehicleCategory(
name: _json['name'] as String ?? '',
icon: _json['icon'] as String ?? '',
model:
VehicleModel.fromJson(_json['model'] as List ?? []));
}
}
class VehicleModel {
final String name;
final String id;
VehicleModel({#required this.name, #required this.id});
static List<VehicleModel> fromJson(List _list) {
List<VehicleModel> result = [];
for (var item in _list) {
var address = VehicleModel(
name: item['name'] as String,
id: item['id'] as String,
);
result.add(address);
}
return result;
}
}
then use it like this:
List<Vehicle> _list = Vehicle.fromJson(_myJson);
return ListView.builder(
itemCount: _list.length,
itemBuilder: (context, i) {
return Column(
children: [
ListView.builder(
itemCount: _list[i].category.model.length,
itemBuilder: (context, j) {
return Text(_list[i].category.model[j].name);
},
)
],
);
},
);

Flutter: Join specific field of JSON file together to become a list itself

I have a json file with a list of different types of data.
I wanted to join the "name" field of all attractions of each city together as a list.
The expected result after joining, for example for Longo city will be like this:
Attraction1
Attraction2
The data in JSON file is structured like this:
{
"city": "London",
"attractions": [
{
"name": "Attraction1",
"localrank": 10,
"intrank": 4
},
{
"name": "Attraction2",
"localrank": 4,
"intrank": 5
}
]
},
{
"city": "Hong Kong",
"attractions": [
{
"name": "Attraction3",
"localrank": 10,
"intrank": 4
},
{
"name": "Attraction4",
"localrank": 4,
"intrank": 5
}
]
},
{
"city": "Cario",
"attractions": [
{
"name": "Attraction5",
"localrank": 10,
"intrank": 4
},
{
"name": "Attraction6",
"localrank": 4,
"intrank": 5
}
]
}
]
I used the following code, but I get an error :
cities.attractions.name.join("\n")
Json model class is this:
List<Cities> citiesFromJson(String str) =>
List<Cities>.from(json.decode(str).map((x) => Cities.fromJson(x)));
String citiesToJson(List<Cities> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Cities {
Cities({
this.city,
this.attractions,
});
String city;
List<Attraction> attractions;
factory Cities.fromRawJson(String str) => Cities.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Cities.fromJson(Map<String, dynamic> json) => Cities(
city: json["city"],
attractions: List<Attraction>.from(
json["attractions"].map((x) => Attraction.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"city": city,
"attractions": List<dynamic>.from(attractions.map((x) => x.toJson())),
};
}
class Attraction {
Attraction({
this.name,
this.localrank,
this.intrank,
});
String name;
int localrank;
int intrank;
factory Attraction.fromRawJson(String str) =>
Attraction.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Attraction.fromJson(Map<String, dynamic> json) => Attraction(
name: json["name"],
localrank: json["localrank"],
intrank: json["intrank"],
);
Map<String, dynamic> toJson() => {
"name": name,
"localrank": localrank,
"intrank": intrank,
};
}
And this also calling json file:
Future<String> fetchData() async {
String data =
await DefaultAssetBundle.of(context).loadString("assets/data.json");
final jsonResult = json.decode(data);
print('$jsonResult oop');
this.setState(() {
jsonResult.forEach(
(element) => Globals.citylist.add(new Cities.fromJson(element)));
});
return "Success!";
}
Something like that should work:
import 'dart:convert';
var data = """ [{
"city": "London",
"attractions": [
{
"name": "Attraction1",
"localrank": 10,
"intrank": 4
},
{
"name": "Attraction2",
"localrank": 4,
"intrank": 5
}
]
},
{
"city": "Hong Kong",
"attractions": [
{
"name": "Attraction3",
"localrank": 10,
"intrank": 4
},
{
"name": "Attraction4",
"localrank": 4,
"intrank": 5
}
]
},
{
"city": "Cario",
"attractions": [
{
"name": "Attraction5",
"localrank": 10,
"intrank": 4
},
{
"name": "Attraction6",
"localrank": 4,
"intrank": 5
}
]
}
] """;
List<Cities> citiesFromJson(String str) =>
List<Cities>.from(json.decode(str).map((x) => Cities.fromJson(x)));
String citiesToJson(List<Cities> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Cities {
Cities({
this.city,
this.attractions,
});
String city;
List<Attraction> attractions;
factory Cities.fromRawJson(String str) => Cities.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Cities.fromJson(Map<String, dynamic> json) => Cities(
city: json["city"],
attractions: List<Attraction>.from(
json["attractions"].map((x) => Attraction.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"city": city,
"attractions": List<dynamic>.from(attractions.map((x) => x.toJson())),
};
}
class Attraction {
Attraction({
this.name,
this.localrank,
this.intrank,
});
String name;
int localrank;
int intrank;
factory Attraction.fromRawJson(String str) =>
Attraction.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Attraction.fromJson(Map<String, dynamic> json) => Attraction(
name: json["name"],
localrank: json["localrank"],
intrank: json["intrank"],
);
Map<String, dynamic> toJson() => {
"name": name,
"localrank": localrank,
"intrank": intrank,
};
}
class Globals {
static List<Cities> citylist = [];
}
Future<String> fetchData() async {
// String data =
// await DefaultAssetBundle.of(context).loadString("assets/data.json");
final jsonResult = json.decode(data);
print('$jsonResult oop');
// this.setState(() {
jsonResult.forEach(
(element) => Globals.citylist.add(new Cities.fromJson(element)));
// });
var result = getAttractionsByCity('London');
print(result.join('\n'));
return "Success!";
}
List<String> getAttractionsByCity(String value) {
var result = <String>[];
for (final city in Globals.citylist) {
if (city.city == value) {
final attractions = city.attractions;
for (final attraction in attractions) {
result.add(attraction.name);
}
}
}
return result;
}
void main() async {
await fetchData();
}
It's a working example. You can copy and paste this code to HTTP://dartpad.dev and run it to see the result.

Flutter: How to map a Dictionary? Make dropdown options via dictionary

I need some help in flutter data mapping. I have a JSON object that is returning some fields. I have to create a form depending on those fields. The issue that I am facing right now is that I cannot map the JSON dictionary to my dropdown list.
So basically I want to create a dropdown options that are in form_field_options of my json.
Here is a code sample of what I am trying to active, JSON return by my server is:
{
"status": "200",
"request": "0",
"message": "Success",
"data": {
"assetID": "155",
"assetTitle": "TPO",
"formTitle": "Roof Asset",
"preFields": [
{
"unique_id": "uid_201955451258",
"form_name": "General Overview",
"form_field_type": "100",
"form_field_required": "0",
"form_field_private": "0",
"form_field_duplicate_times": "00",
"form_field_disabledrow": "0"
},
{
"unique_id": "uid_201939764918",
"form_name": "Asset ID",
"form_field_type": "5",
"form_field_required": "1",
"form_field_private": "0",
"form_field_duplicate_times": "00",
"form_field_disabledrow": "0"
},
{
"unique_id": "uid_201789014253",
"form_name": "Facility ID",
"form_field_type": "5",
"form_field_required": "0",
"form_field_private": "0",
"form_field_duplicate_times": "00",
"form_field_disabledrow": "0"
},
{
"unique_id": "uid_201996716360",
"form_name": "Location",
"form_field_type": "19",
"form_field_required": "0",
"form_field_private": "0",
"form_field_duplicate_times": "00",
"form_field_disabledrow": "0"
},
{
"unique_id": "uid_201941758250",
"form_name": "Developed Area Type",
"form_field_type": "1",
"form_field_required": "0",
"form_field_private": "0",
"form_field_duplicate_times": "00",
"form_field_options": {
"1": {
"opt_name": "Suburban",
"opt_weightage": ""
},
"2": {
"opt_name": "Urban",
"opt_weightage": ""
},
"3": {
"opt_name": "Rural",
"opt_weightage": ""
}
},
"form_field_disabledrow": "0"
}
]
}
}
And here is my form class (auto generate class form quicktype) is:
// To parse this JSON data, do
//
// final form = formFromJson(jsonString);
import 'dart:convert';
Form formFromJson(String str) => Form.fromJson(json.decode(str));
String formToJson(Form data) => json.encode(data.toJson());
class Form {
String status;
String request;
String message;
Data data;
Form({
this.status,
this.request,
this.message,
this.data,
});
factory Form.fromJson(Map<String, dynamic> json) => new Form(
status: json["status"],
request: json["request"],
message: json["message"],
data: Data.fromJson(json["data"]),
);
Map<String, dynamic> toJson() => {
"status": status,
"request": request,
"message": message,
"data": data.toJson(),
};
}
class Data {
String assetId;
String assetTitle;
String formTitle;
List<PreField> preFields;
Data({
this.assetId,
this.assetTitle,
this.formTitle,
this.preFields,
});
factory Data.fromJson(Map<String, dynamic> json) => new Data(
assetId: json["assetID"],
assetTitle: json["assetTitle"],
formTitle: json["formTitle"],
preFields: new List<PreField>.from(json["preFields"].map((x) => PreField.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"assetID": assetId,
"assetTitle": assetTitle,
"formTitle": formTitle,
"preFields": new List<dynamic>.from(preFields.map((x) => x.toJson())),
};
}
class PreField {
String uniqueId;
String formName;
String formFieldType;
String formFieldRequired;
String formFieldPrivate;
String formFieldDuplicateTimes;
String formFieldDisabledrow;
Map<String, FormFieldOption> formFieldOptions;
PreField({
this.uniqueId,
this.formName,
this.formFieldType,
this.formFieldRequired,
this.formFieldPrivate,
this.formFieldDuplicateTimes,
this.formFieldDisabledrow,
this.formFieldOptions,
});
factory PreField.fromJson(Map<String, dynamic> json) => new PreField(
uniqueId: json["unique_id"],
formName: json["form_name"],
formFieldType: json["form_field_type"],
formFieldRequired: json["form_field_required"],
formFieldPrivate: json["form_field_private"],
formFieldDuplicateTimes: json["form_field_duplicate_times"],
formFieldDisabledrow: json["form_field_disabledrow"],
formFieldOptions: json["form_field_options"] == null ? null : new Map.from(json["form_field_options"]).map((k, v) => new MapEntry<String, FormFieldOption>(k, FormFieldOption.fromJson(v))),
);
Map<String, dynamic> toJson() => {
"unique_id": uniqueId,
"form_name": formName,
"form_field_type": formFieldType,
"form_field_required": formFieldRequired,
"form_field_private": formFieldPrivate,
"form_field_duplicate_times": formFieldDuplicateTimes,
"form_field_disabledrow": formFieldDisabledrow,
"form_field_options": formFieldOptions == null ? null : new Map.from(formFieldOptions).map((k, v) => new MapEntry<String, dynamic>(k, v.toJson())),
};
}
class FormFieldOption {
String optName;
String optWeightage;
FormFieldOption({
this.optName,
this.optWeightage,
});
factory FormFieldOption.fromJson(Map<String, dynamic> json) => new FormFieldOption(
optName: json["opt_name"],
optWeightage: json["opt_weightage"],
);
Map<String, dynamic> toJson() => {
"opt_name": optName,
"opt_weightage": optWeightage,
};
}
Now when I try to apply loop or mapping on my options list (Which runs perfectly if its list) like this, It will not map it:
Column(
children: <Widget>[
FormBuilderDropdown(
attribute: item.uniqueId,
decoration:
InputDecoration(labelText: item.formName),
// initialValue: 'Male',
hint: Text(item.formName),
// validators: [
// FormBuilderValidators.required()
// ],
items: item.formFieldOptions.map((option) => DropdownMenuItem(
value: option,
child: Text("$option.optName")))
.toList(),
),
],
),
It throws me error that:
> The argument type '(String) → MapEntry<?, ?>' can't be assigned to the
> parameter type '(String, FormFieldOption) → MapEntry<dynamic,
> dynamic>'.dart(argument_type_not_assignable)
Please help or let me know what am I doing wrong. How can I make those dropdown options.
Thanks in advance
You sould try to map with the correct lambda signature (k, v) =>
items: item.formFieldOptions.map((key, option) => DropdownMenuItem(
value: key,
child: Text("${option.optName}"),
)
).toList()