I have data from API like this :
{
"data": {
"1": [
{
"id": 31,
"customer_id": 2,
"product_variant_id": 123,
"quantity": 5,
"partner_id": 1
},
{
"id": 30,
"customer_id": 2,
"product_variant_id": 109,
"quantity": 2,
"partner_id": 1
}
],
"3": [
{
"id": 29,
"customer_id": 2,
"product_variant_id": 107,
"quantity": 8,
"partner_id": 3,
}
]
},
"code": 200,
"msg": "Data All Cart"
}
and here's the cartModel :
class CartMetadata {
CartMetadata({
required this.data,
required this.code,
required this.msg,
});
final Map<String, List<CartModel>> data;
final int code;
final String msg;
factory CartMetadata.fromJson(Map<String, dynamic> json) => CartMetadata(
data: Map.from(json["data"]).map((k, v) => MapEntry<String, List<CartModel>>(k,
List<CartModel>.from(v.map((x) => CartModel.fromJson(x))))),
code: json["code"],
msg: json["msg"],
);
Map<String, dynamic> toJson() => {
"data": Map.from(data).map((k, v) => MapEntry<String, dynamic>(k,
List<dynamic>.from(v.map((x) => x.toJson())))),
"code": code,
"msg": msg,
};
}
class CartModel {
CartModel({
required this.id,
required this.customerId,
required this.productVariantId,
required this.quantity,
required this.partnerId,
});
final int id;
final int customerId;
final int productVariantId;
final int quantity;
final int partnerId;
factory CartModel.fromJson(Map<String, dynamic> json) => CartModel(
id: json["id"],
customerId: json["customer_id"],
productVariantId: json["product_variant_id"],
quantity: json["quantity"],
partnerId: json["partner_id"],
);
Map<String, dynamic> toJson() => {
"id": id,
"customer_id": customerId,
"product_variant_id": productVariantId,
"quantity": quantity,
"partner_id": partnerId,
};
}
I was using this variable :
final jsonMap = CartMetadata.fromJson(jsonDecode(response.body));
CartModel? cart;
And the result I need is specific data with specific id, example for id == 30 :
cart = { "id": 30, "customer_id": 2, "product_variant_id": 109,
"quantity": 2, "partner_id": 1 }
I know I should used 'where' function, but I already try and the problem I should use array on jsonMap.data[array].
Anyone can give advice?
Just use,
Way: 1 - use map and array
jsonMap.data["1"]?[1]
// "1" is key of data or partner_id
// 1 is index of array
// ? is for null safety
Way: 2 - Make extension
extension GetCartItem on CartMetadata {
CartModel? cartItem(int partnerId, int index){
return data["$partnerId"]?[index];
}
}
usage,
jsonMap.cartItem(1,1) // return CartItem or null, Don't forget to import extension :)
function calling
ElevatedButton(
onPressed: () {
findItem(30);
},
child: Text("click")),
Pass item id
findItem(int id) {
final cartMeta = CartMetadata.fromJson(json);
CartModel? data1;
cartMeta.data.forEach((key, value) {
value.forEach((element) {
if (element.id == id) data1 = element;
});
});
print("result ==> ${data1?.toJson()}");
}
Result ScreenShot
use
cart.toJson()
which is already written in your data class to get a json in that specified format
In my opinion just use cart.<variable_name> to access instead of doing same work multiple time json if you really need use the above wholde code will be
final jsonMap = CartMetadata.fromJson(jsonDecode(response.body));
CartModel? cart = jsonMap.data['1'].single; //1 is the key of the data and if you want specific cart use where condition or get through a index like [0] {int inside}
try this might help but also try other might also have more easy to follow
// put the data to your model e.g.
final converttoModel = CartMetadata.fromJson(jsondata);
then try to use entries and get the value data
final find = converttoModel.data.entries
.map((e)=> e.value)
.map((e) => e.where((e)=> e.id == 31)
.first.toJson());
// then print the data or log it on debug console
log(find.first.toString());
as the result data would get is id 31
{id: 31, customer_id: 2, product_variant_id: 123, quantity: 5, partner_id: 1}
Related
Flutter 3.3.9 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b8f7f1f986 (hace 2 semanas) • 2022-11-23 06:43:51 +0900
Engine • revision 8f2221fbef
Tools • Dart 2.18.5 • DevTools 2.15.0
hello, best regards and I hope you are well, I have spent the last few hours trying to solve the error in the title of the issue, and I have not been able to, could you explain to me a way to solve it, I have attached the model that I am using and the response of the request to an api, thank you very much in advance
base_response_model.dart
import 'package:json_annotation/json_annotation.dart';
part 'base_response_model.g.dart';
#JsonSerializable()
class BaseResponseModel {
final int page;
#JsonKey(name: 'page_size')
final int pageSize;
final int total;
final int pages;
#JsonKey(name: 'prev_page', defaultValue: 0)
final dynamic prevPage;
#JsonKey(name: 'next_page', defaultValue: 0)
final dynamic nextPage;
BaseResponseModel({
required this.page,
required this.pageSize,
required this.total,
required this.pages,
required this.prevPage,
required this.nextPage,
});
factory BaseResponseModel.fromJson(Map<String, dynamic> json) =>
_$BaseResponseModelFromJson(json);
Map<String, dynamic> toJson() => _$BaseResponseModelToJson(this);
}
get_municipalities_by_province_response_model.dart
import 'package:delivery/app/data/models/andariego/andariego_models/municipality_model.dart';
import 'package:delivery/app/data/models/andariego/andariego_response_models/base_response_model.dart';
import 'package:json_annotation/json_annotation.dart';
part 'get_municipalities_by_province_response_model.g.dart';
#JsonSerializable()
class GetMunicipalitiesByProvinceResponseModel extends BaseResponseModel {
final List<MunicipalityModel> data;
GetMunicipalitiesByProvinceResponseModel({
required super.page,
required super.pageSize,
required super.total,
required super.pages,
required super.prevPage,
required super.nextPage,
required this.data,
});
factory GetMunicipalitiesByProvinceResponseModel.fromJson(
Map<String, dynamic> json) =>
_$GetMunicipalitiesByProvinceResponseModelFromJson(json);
#override
Map<String, dynamic> toJson() =>
_$GetMunicipalitiesByProvinceResponseModelToJson(this);
}
municipality_model.dart
import 'package:delivery/app/data/models/andariego/andariego_models/base_andariego_model.dart';
import 'package:json_annotation/json_annotation.dart';
part 'municipality_model.g.dart';
#JsonSerializable()
class MunicipalityModel extends BaseAndariegoModel {
final int parent;
MunicipalityModel({
required super.id,
required super.name,
required this.parent,
});
factory MunicipalityModel.fromJson(Map<String, dynamic> json) =>
_$MunicipalityModelFromJson(json);
#override
Map<String, dynamic> toJson() => _$MunicipalityModelToJson(this);
}
api_response.json
{
"page": 1,
"page_size": 20,
"total": 11,
"pages": 1,
"prev_page": null,
"next_page": null,
"data": [
{
"id": 1188,
"name": "Consolación del Sur",
"parent": 58
},
{
"id": 1132,
"name": "Guane",
"parent": 58
},
{
"id": 1125,
"name": "La Palma",
"parent": 58
},
{
"id": 1124,
"name": "Los Palacios",
"parent": 58
},
{
"id": 1186,
"name": "Mantua",
"parent": 58
},
{
"id": 1182,
"name": "Minas de Matahambre",
"parent": 58
},
{
"id": 1189,
"name": "Pinar del Rio",
"parent": 58
},
{
"id": 1165,
"name": "Sandino",
"parent": 58
},
{
"id": 1133,
"name": "San Juan y Martínez",
"parent": 58
},
{
"id": 1187,
"name": "San Luis",
"parent": 58
},
{
"id": 1169,
"name": "Viñales",
"parent": 58
}
]
}
Generated code
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'base_response_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
BaseResponseModel _$BaseResponseModelFromJson(Map<String, dynamic> json) =>
BaseResponseModel(
page: json['page'] as int,
pageSize: json['page_size'] as int,
total: json['total'] as int,
pages: json['pages'] as int,
prevPage: json['prev_page'] ?? 0,
nextPage: json['next_page'] ?? 0,
);
Map<String, dynamic> _$BaseResponseModelToJson(BaseResponseModel instance) =>
<String, dynamic>{
'page': instance.page,
'page_size': instance.pageSize,
'total': instance.total,
'pages': instance.pages,
'prev_page': instance.prevPage,
'next_page': instance.nextPage,
};
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'get_municipalities_by_province_response_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
GetMunicipalitiesByProvinceResponseModel
_$GetMunicipalitiesByProvinceResponseModelFromJson(
Map<String, dynamic> json) =>
GetMunicipalitiesByProvinceResponseModel(
page: json['page'] as int,
pageSize: json['page_size'] as int,
total: json['total'] as int,
pages: json['pages'] as int,
prevPage: json['prev_page'] ?? 0,
nextPage: json['next_page'] ?? 0,
data: (json['data'] as List<dynamic>)
.map((e) => MunicipalityModel.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$GetMunicipalitiesByProvinceResponseModelToJson(
GetMunicipalitiesByProvinceResponseModel instance) =>
<String, dynamic>{
'page': instance.page,
'page_size': instance.pageSize,
'total': instance.total,
'pages': instance.pages,
'prev_page': instance.prevPage,
'next_page': instance.nextPage,
'data': instance.data,
};
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'municipality_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
MunicipalityModel _$MunicipalityModelFromJson(Map<String, dynamic> json) =>
MunicipalityModel(
id: json['id'] as int,
name: json['name'] as String,
parent: json['parent'] as int,
);
Map<String, dynamic> _$MunicipalityModelToJson(MunicipalityModel instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'parent': instance.parent,
};
I am using flutter, null safety
It looks like a field is missing (or null) in the JSON causing that problem. The line number should point you to the right spot!
Below output sample returning by the server which i should use Dart classes to create data class from them
const cities = """[
{
"id": 1,
"province_id": 1,
"name": "test1",
"neighborhood": []
},
{
"id": 2,
"province_id": 1,
"name": "test2",
"neighborhood": [
{"id": 1, "city_id": 1, "name": "xxx 1"},
{"id": 2, "city_id": 1, "name": "xxx 2"}
]
}
]
""";
as you can see cities is an Array and into that neighborhood is as array too
data class which i implemented for them:
#freezed
class City with _$City {
const factory City(
final int id,
#JsonKey(name: 'province_id') final int provinceId,
final String name,
final List<Neighborhood>? neighborhood,
) = _City;
factory City.fromJson(Map<String, dynamic> json) => _$CityFromJson(json);
}
#freezed
class Neighborhood with _$Neighborhood {
const factory Neighborhood(
final int id,
#JsonKey(name: 'city_id') final int cityId,
final String name,
) = _Neighborhood;
factory Neighborhood.fromJson(Map<String, dynamic> json) => _$NeighborhoodFromJson(json);
}
and now when i try to use this code to convert json data i get error:
final List<Map<String,dynamic>> data = json.decode(cities) as List<Map<String,dynamic>>;
final city = data.map((elements) => City.fromJson(elements)).toList();
Error:
The argument type 'Map<String, dynamic> Function(dynamic)' can't be assigned to the parameter type 'Iterable<dynamic>'.
You should be mapping the result like
final l = json.decode(cities);
List<City> city = l.map((elements) => City.fromJson(elements)).toList();
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
I want to convert my object into JSON so I implemented following code
import "package:behoove/models/product.dart";
class Order {
Product _product;
int _quantity;
int _id;
Order(this._product, this._quantity, this._id);
int get id => _id;
int get quantity => _quantity;
Product get product => _product;
double get orderPrice => _quantity * double.parse(_product.discountedPrice ?? _product.price);
Map<String, dynamic> toJson() => {
"id": _product.id.toString(),
"name": _product.name,
"price": _product.price,
"quantity": _quantity.toString(),
"attributes": {},
"conditions": []
};
}
JSON from app is
{id: 9, name: GoldStar Classic 032, price: 1200, quantity: 1, attributes: {}, conditions: []}}
Screenshot JSON from app
But JSON from DartPad is
{"id":"1","name":"Sabin","price":200,"quantity":3,"attributes":{},"conditions":[]}
Screenshot JSON from DartPad console
How can I get same output on my app. please help. Also why is it not similar on both DartPad and app?
Instead of calling .toJson() directly use jsonEncode() as in the example (you can run it in DartPad to see difference). Calling jsonEncode(order) will give you a properly formatted json.
import 'dart:convert';
void main() {
final obj = Order();
print(obj.toJson());
print(jsonEncode(obj));
}
class Order {
int id = 0;
int price = 100;
String name = 'asdf';
int quantity = 10;
Map<String, dynamic> toJson() => {
"id": id.toString(),
"name": name,
"price": price,
"quantity": quantity.toString(),
"attributes": {},
"conditions": []
};
}
Output:
// simple toJson that ommits quotation marks
{id: 0, name: asdf, price: 100, quantity: 10, attributes: {}, conditions: []}
// properly encoded json
{"id":"0","name":"asdf","price":100,"quantity":"10","attributes":{},"conditions":[]}
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).