How to get json array in Flutter/Dart - json

I would want to get the data for all "name" only from the array data.
I want to print(data['data']['name']);
But it returns this error:
Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
But when I print(data['data']);, it will return all data from "data":
"data": [
{
"created_at": "2020-03-16 16:10:51",
"deleted_at": null,
"id": 2,
"is_active": 1,
"name": "Maybank",
"updated_at": "2020-03-16 16:18:06"
},
{
"created_at": "2020-03-16 16:27:37",
......
],
Call API Code
displayBanks(BuildContext context) async {
_callApi.refreshTokenApi(context);
var _addressUrl = '$_hostUrl/banks'; //API URL
final SharedPreferences prefs = await SharedPreferences.getInstance();
_accessToken = prefs.getString('access_token');
Response _response = await get(_addressUrl, headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $_accessToken'
});
var data;
data = jsonDecode(_response.body);
if (_response.statusCode == 200) {
print(data['data']['name']);
return data;
}
else {
print(_response.statusCode);
}
}
SAMPLE JSON DATA FROM API URL:
{
"data": [
{
"created_at": "2020-03-16 16:10:51",
"deleted_at": null,
"id": 2,
"is_active": 1,
"name": "Maybank",
"updated_at": "2020-03-16 16:18:06"
},
{
"created_at": "2020-03-16 16:27:37",
"deleted_at": null,
"id": 3,
"is_active": 1,
"name": "India International Bank (Malaysia) Berhad",
"updated_at": "2020-03-16 16:27:37"
},
{
"created_at": "2020-03-16 16:27:37",
"deleted_at": null,
"id": 4,
"is_active": 1,
"name": "National Bank of Abu Dhabi Malaysia Berhad",
"updated_at": "2020-03-16 16:27:37"
}
],
"links": {
"first": "https://demo.local/api/banks?page=1",
"last": "https://demo.local/api/banks?page=1",
"next": null,
"prev": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "https://demo.local/api/banks",
"per_page": 5,
"to": 3,
"total": 3
}
}

Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
The exception message explains the issue clearly.
The property 'name' is inside an object which itself placed in an array. So you first decode the array. Then access each object using the index (0..n), then from each object, you can read the 'name' property.
Here you go
class MyData {
final List<Data> data;
MyData({this.data});
factory MyData.fromJson(Map<String, dynamic> json) {
return MyData(
data: json['data'] != null ? (json['data'] as List).map((i) => Data.fromJson(i)).toList() : null,
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data.map((v) => v.toJson()).toList();
}
return data;
}
}
class Data {
final String created_at;
final String deleted_at;
final int id;
final int is_active;
final String name;
final String updated_at;
Data({this.created_at, this.deleted_at, this.id, this.is_active, this.name, this.updated_at});
factory Data.fromJson(Map<String, dynamic> json) {
return Data(
created_at: json['created_at'],
deleted_at: json['deleted_at'],
id: json['id'],
is_active: json['is_active'],
name: json['name'],
updated_at: json['updated_at'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['created_at'] = this.created_at;
data['id'] = this.id;
data['is_active'] = this.is_active;
data['name'] = this.name;
data['updated_at'] = this.updated_at;
data['deleted_at'] = this.deleted_at;
return data;
}
}

The error makes sense. The 'data' attribute in your JSON is array. So, you'll have to pass index of the item to access 'name' attribute - something like - data['data'][0]['name'] to get 'Maybank'.
Ideally, you should have a class which creates the instance from the JSON. In this case, the code snippet will look like :
Banks banks = new Banks.fromJson(data)
Now, you can use sites like this to create a class definition (including.fromJson).

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']);

How to get the object from array from api response in flutter

I'm trying to integrate the api using class model. here is my api response look like.
{
"status": 1,
"message": "your rides",
"data": [
{
"id": 2,
"ride_user_id": "4",
"ride_driver_id": "2",
"pick_up": "gsdhjhsgdf",
"drop_of": "dsfbsdjbf",
"date": null,
"time": "10.55",
"status": "complete",
"created_at": "2022-06-17T09:50:25.000000Z",
"updated_at": "2022-06-17T09:56:37.000000Z",
"driver": {
"id": 2,
"name": "driver",
"vehicle_number": null,
"licence_number": null,
"state": null,
"image": null,
"notification": 1,
"created_at": "2022-06-08T16:15:12.000000Z",
"updated_at": "2022-06-08T16:15:44.000000Z"
},
"rideperson": {
"id": 4,
"name": "ab",
"vehicle_number": null,
"licence_number": null,
"state": "ascascas",
"image": "profile/1735772987889499.jfif",
"notification": 1,
"created_at": "2022-06-09T07:54:41.000000Z",
"updated_at": "2022-06-16T06:48:37.000000Z"
},
"rating": {
"id": 2,
"sender_id": null,
"reciever_id": null,
"ride_id": 2,
"rating": "4",
"created_at": "2022-06-17T09:59:38.000000Z",
"updated_at": "2022-06-17T09:59:38.000000Z"
}
}
]
}
and here is my model
import 'dart:convert';
import 'package:flutter/foundation.dart';
MyRides rideFromJson(String str) => MyRides.fromJson(json.decode(str));
String rideToJson(MyRides data) => json.encode(data.toJson());
class MyRidesDetails {
final int id;
final String pickUp;
final String dropOff;
final String time;
final String rideUserId;
final String rideDriverId;
final List driver;
MyRidesDetails(
{required this.id,
required this.pickUp,
required this.dropOff,
required this.time,
required this.rideUserId,
required this.rideDriverId,
required this.driver
});
factory MyRidesDetails.fromJson(Map<String, dynamic> json) => MyRidesDetails(
id: json['id'],
dropOff: json['drop_of'],
pickUp: json['pick_up'],
time: json['time'],
rideUserId: json['ride_user_id'],
rideDriverId: json['ride_driver_id'],
driver: json['data']['driver']
);
Map<String, dynamic> toJson() => {
'id': id,
'drop_of': dropOff,
'pick_up': pickUp,
'time':time,
'rating':time,
'ride_user_id':rideUserId,
'ride_driver_id':rideDriverId,
'driver':driver
};
}
class MyRides {
MyRides({
required this.status,
required this.message,
required this.data,
});
int status;
String message;
List<MyRidesDetails> data;
factory MyRides.fromJson(Map<String, dynamic> json) => MyRides(
status: json["status"],
message: json["message"],
data: List<MyRidesDetails>.from(json["data"].map((x) => MyRidesDetails.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"message": message,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
here is the code how i'm populating data on my model
Future getAllMyRides(role) async {
Map<String, String> headers = {
"Content-type": "application/json",
'Authorization': 'Bearer $token',
};
var url = Uri.parse(ApiPath.getAllMyRidesUrl+role);
final response = await http.get(url, headers: headers);
if (response.statusCode == 200) {
return rideFromJson(response.body).data;
} else {
throw Exception('Failed to load post');
}
}
Now, the question is i want to access this object
"driver": {
"id": 2,
"name": "driver",
"vehicle_number": null,
"licence_number": null,
"state": null,
"image": null,
"notification": 1,
"created_at": "2022-06-08T16:15:12.000000Z",
"updated_at": "2022-06-08T16:15:44.000000Z"
},
using the same model. My model is only accessing the data which is not in object, i want to create a list variable or something on my mode which can access those data which is in object form.
here is the code how i'm calling api function on ui screen
getAllMyRides() async {
setState(() {
_isLoading = true;
});
await Future.delayed(const Duration(seconds: 2), () async {
connectionMsg = await services.checkInternetConnectivity();
if (connectionMsg == "connected") {
try {
var _myRides = await services.getAllMyRides(role);
if (myRides is MyRides) {
print(_myRides.data[0].driver.id); //this should print 2
} else {
print("Unable to fetch data");
}
setState(() {
_isLoading = false;
});
} catch (e) {
print(e);
setState(() {
apiCrashed = true;
});
}
setState(() {
_isLoading = false;
});
} else if (connectionMsg == "not connected") {
AppDialogs().showInfoDialogue(context, "Internet is not working!", () {
Navigator.pop(context);
});
setState(() {
_isLoading = false;
});
}
});
}
#override
void initState() {
super.initState();
getAllMyRides();
}
please help how to do this.Thanks.
var _myRides = await getAllMyRides();
var jsonDecoded = json.decode(_myRides);
print(jsonDecoded['data'][0]['driver']['id']);
please try this

how to get list of keys and list of value from a single json in flutter

i have a json
{
"result": [
{
"id": 2,
"e_id": 2,
"e_name": "0",
"abc": 0,
"doa": "2021-02-15 13:17:11"
},
{
"id": 3,
"e_id": 22,
"e_name": "ok",
"abc": 1,
"doa": "2021-02-15 13:17:57"
}
],
"status": 1,
"msg": "Successfully fetched"
}
.
How i want two list like
List keyList=[
"id","e_id","e_name","abc","doa"];
and
List valueList=[
{
2, 2,"0",0,"2021-02-15 13:17:11"
},
{
3, 22,"ok",1,"2021-02-15 13:17:57"
}
];
anyOne who can help me??
how to get list of keys and list of value, both are separate lists and fetch only from single json which is given above.
here is my model class---
class DataModel {
List<Result> result;
int status;
String msg;
DataModel({this.result, this.status, this.msg});
DataModel.fromJson(Map<String, dynamic> json) {
if (json['result'] != null) {
result = new List<Result>();
json['result'].forEach((v) {
result.add(new Result.fromJson(v));
});
}
status = json['status'];
msg = json['msg'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.result != null) {
data['result'] = this.result.map((v) => v.toJson()).toList();
}
data['status'] = this.status;
data['msg'] = this.msg;
return data;
}
}
class Result {
int id;
int eId;
String eName;
String abc;
String doa;
Result(
{this.id,
this.eId,
this.eName,
this.abc,
this.doa});
Result.fromJson(Map<String, dynamic> json) {
id = json['id'];
eId = json['e_id'];
eName = json['e_name'];
abc= json['abc'];
doa = json['doa'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['e_id'] = this.eId;
data['e_name'] = this.eName;
data['abc'] = this.abc;
data['doa'] = this.doa;
return data;
}
}
i dont need model mapping,
i need only two different list- one is keyList and other one is valuelist form the result.
kindly help me to get this lists
Map<String, dynamic> json ={
"result": [
{
"id": 2,
"e_id": 2,
"e_name": "0",
"abc": 0,
"doa": "2021-02-15 13:17:11"
},
{
"id": 3,
"e_id": 22,
"e_name": "ok",
"abc": 1,
"doa": "2021-02-15 13:17:57"
}
],
"status": 1,
"msg": "Successfully fetched"
};
List<String> keyList;
List<List<dynamic>> valueList = [];
json["result"].forEach((entry) {
keyList ??= entry.keys;
valueList.add(entry.values);
});
Here is the code which gives you key and values as a List:
You can copy and try it out on dartpad.dev
import 'dart:convert';
String json = '''
{
"result": [
{
"id": 2,
"e_id": 2,
"e_name": "0",
"abc": 0,
"doa": "2021-02-15 13:17:11"
},
{
"id": 3,
"e_id": 22,
"e_name": "ok",
"abc": 1,
"doa": "2021-02-15 13:17:57"
}
],
"status": 1,
"msg": "Successfully fetched"
}
''';
void main() {
Map<String, dynamic> map = jsonDecode(json);
List<String> keyList = map['result'][0].keys.toList();
List<dynamic> listOfValues = [];
List<dynamic> valueList = map['result'];
for(int i=0; i < valueList.length; i++) {
Map<String, dynamic> obj = valueList[i];
listOfValues.addAll(obj.values);
}
keyList.forEach(print);
print('\n\n');
listOfValues.forEach(print);
}
Output by printing each element of both arrays:
id
e_id
e_name
abc
doa
2
2
0
0
2021-02-15 13:17:11
3
22
ok
1
2021-02-15 13:17:57
Use rootBundle.loadString('assets/json_file.json');
and then json.decode(jsonString);
Now you can use it normally

Flutter : JSON.parse fail on empty string

I am trying to parse JSON data in Flutter and it is working fine.
But when some data is empty or null then it is not working and giving error.
import 'dart:convert';
GetFollowing getFollowingFromJson(String str) => GetFollowing.fromJson(json.decode(str));
class GetFollowing {
List<Content> content;
int count;
bool success;
String error;
GetFollowing({
this.error,
this.content,
this.count,
this.success,
});
factory GetFollowing.fromJson(Map<String, dynamic> json) => GetFollowing(
error: json["error"],
content: List<Content>.from(json["content"].map((x) => Content.fromJson(x))),
count: json["count"],
success: json["success"],
);
}
class Content {
int uid;
int following;
String name;
String profilePhoto;
String baseLocation;
String registrationDate;
String country;
Content({
this.uid,
this.following,
this.name,
this.profilePhoto,
this.baseLocation,
this.registrationDate,
this.country,
});
factory Content.fromJson(Map<String, dynamic> json) => Content(
uid: json["uid"] ?? null,
following: json["following"] ?? null,
name: json["name"] ?? null,
profilePhoto: json["profile_photo"] ?? null,
baseLocation: json["base_location"] ?? null,
registrationDate: json["registration_date"] ?? null,
country: json["country"] ?? null,
);
}
Here is the sample data.
Scenario
{"error":"No record found.","success":false}
Scenario
{
"content": [{
"uid": 34,
"following": 35,
"name": "Sadi",
"profile_photo": "noimage.png",
"base_location": "New Delhi",
"registration_date": "03-05-2020",
"country": "India"
}, {
"uid": 34,
"following": 37,
"name": "Sameer",
"profile_photo": "noimage.png",
"base_location": "New Delhi",
"registration_date": "03-05-2020",
"country": "India"
}, {
"uid": 34,
"following": 36,
"name": "Simran",
"profile_photo": "noimage.png",
"base_location": "New Delhi",
"registration_date": "03-05-2020",
"country": "India"
}],
"count": 3,
"success": true
}
I am getting error if content is null or empty then parse didn't complete and gives error.
Exception Caught: NoSuchMethodError: The method '[]' was called on null.
content: (json["content"] as List).map((x as Map<String, dynamic>) => Content.fromJson(x)).toList()
Consider json_annotation or built_value to handle all your boiler plate for you.

Dart - type 'String' is not a subtype of type 'Iterable<dynamic>'

I am trying to parse a local JSON file in dart and to display its values.
user.json
[
{
"id": 1,
"name": "Greg",
"imageUrl": "assets/images/greg.jpg"
},
{
"id": 2,
"name": "James",
"imageUrl": "assets/images/james.jpg"
}
]
Here is my chats.json
[
{
"sender": "james",
"time": "5:30 PM",
"text": "Hey, how's it going? What did you do today?",
"isLiked": false,
"unread": true
},
{
"sender": "olivia",
"time": "4:30 PM",
"text": "Hey, how's it going? What did you do today?",
"isLiked": true,
"unread": false
}
]
Here is my Message class
class Message {
final User sender;
final String time;
final String text;
final bool isLiked;
final bool unread;
Message({
this.sender,
this.time,
this.text,
this.isLiked,
this.unread,
});
factory Message.fromJson(Map<String, dynamic> parsedJson){
return Message(
sender: User.fromJson(parsedJson['sender']),
time : parsedJson['time'],
text : parsedJson ['text'],
isLiked : parsedJson['isLiked'],
unread : parsedJson ['unread'],
);
}
static List<User> parseUsers(usersJson) {
List<User> usersList = new List<User>.from(usersJson);
return usersList;
}
}
Here is my user class
class User {
final int id;
final String name;
final String imageUrl;
User({
this.id,
this.name,
this.imageUrl,
});
factory User.fromJson(Map<String, dynamic> parsedJson){
return User(
id: parsedJson['id'],
name : parsedJson['name'],
imageUrl : parsedJson ['imageUrl']
);
}
}
Here is my latest_chat.dart (it's StatefulWidget)
List<Message> _messages = List<Message>();
Future<String> _loadChatsAsset() async {
return await rootBundle.loadString('assets/json/chats.json');
}
Future<List<Message>> loadChats() async {
String jsonString = await _loadChatsAsset();
var messages = List<Message>();
final messagesJson = json.decode(jsonString);
for (var messageJson in messagesJson){
messages.add(Message.fromJson(messageJson));
}
return messages;
}
#override
void initState() {
loadChats().then((value) {
setState(() {
_messages.addAll(value);
});
});
super.initState();
}
To print something from my JSON I usually do _messages[index].sender.name or _messages[index].text etc...
The above parsing method worked without nested objects (for User only).
With nested objects (User inside Message) I am not able to identify the source of the following error.
type 'String' is not a subtype of type 'Iterable'
It's happening on this line of code
List usersList = new List.from(usersJson);
I am not sure what I am missing. Can you please assist?
Thanks in advance
As can be see in your json you are getting just string as a sender but when you are creating Message object then User class requires three arguments.
Means that, as a sender in json there should a user object.
{
"id" : 1
"name" : "Viren"
"imageUrl" : 'someurl'
}
Your json and your desire output is not matching.
Moreover your following line is also wrong.
sender: parseUsers(parsedJson['sender']),
Change to this.
sender: User.fromJson(parsedJson['sender'])
Update:
Your json should be like below.
[
{
"sender": {
"id": 1,
"name": "Greg",
"imageUrl": "assets/images/greg.jpg"
},
"time": "5:30 PM",
"text": "Hey, how's it going? What did you do today?",
"isLiked": false,
"unread": true
},
{
"sender": {
"id": 2,
"name": "James",
"imageUrl": "assets/images/james.jpg"
},
"time": "4:30 PM",
"text": "Hey, how's it going? What did you do today?",
"isLiked": true,
"unread": false
}
]