How to convert object to json in flutter? - json

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":[]}

Related

FLUTTER How to get specific List inside List using where

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}

Dart parsing nested array to data class

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();

Dart Error: type 'List<dynamic>' is not a subtype of type 'String' in retrieving JSON Object within an Object

I am new in Dart and Flutter.
I am trying to access and print certain information from local JSON file. Here is the structure of my myPet.json file:
{
"person":
[
{
"user_id": 23,
"user_name": "Joe Hann",
"user_dob": 1998,
"pets":
[
{
"id": 1,
"name": "Fifi",
"type": "Cat",
"attribute": ["Cute", "Black", "Caring"],
"likes":
{
"hobbies": ["Play Ball", "Outing", "Sleep"],
"food": ["Whiskas", "PowerCat", "Fried Fish"]
},
"dateAdopted": "2020-10-10 11:25:02.155"
},
{
"id": 2,
"name": "Dongo",
"type": "Dog",
"attribute": ["Ferocious", "Loyal", "Big"],
"likes":
{
"hobbies": ["Barking", "Eating", "Sleep"],
"food": ["Chicken", "Biscuit"]
},
"dateAdopted": "2020-8-10 8:10:09.392"
}
]
},
{
"user_id": 17,
"user_name": "Sam Doll",
"user_dob": 1995,
"pets":
[
{
"id": 13,
"name": "Gola",
"type": "Fish",
"attribute": ["Red", "Small", "Speeder"],
"likes":
{
"hobbies": ["Swimming", "Blurbing"],
"food": ["Bread", "PowerCat"]
},
"dateAdopted": "2021-2-20 11:00:08.165"
}
]
}
]
}
Here is my Dart code:
import "dart:convert"; //for json conversion
import "dart:io"; //for input output local file
void main() {
String jsonData = new File('myPet.json').readAsStringSync();
List<Person> _listPerson = [];
_listPerson = Person.allPersonFromJson(jsonData);
print("List of Person:-");
for(int i=0; i<_listPerson.length; i++)
{
print(_listPerson[i].user_id);
print(_listPerson[i].user_name);
print(_listPerson[i].user_dob);
print("");
print("Pets:");
for(int j =0;j<_listPerson[i].pet.length; j++)
{
print(_listPerson[i].pet[j].id);
print(_listPerson[i].pet[j].name);
print(_listPerson[i].pet[j].type);
print("Attributes:-");
for(int k=0;k<_listPerson[i].pet[j].attribute.length;k++)
{
print(_listPerson[i].pet[j].attribute[k]);
}
print("");
}
print("");
print("");
}
}
class Person{
final int user_id;
final String user_name;
final int user_dob;
final List<Pet> pet;
Person ({
required this.user_id,
required this.user_name,
required this.user_dob,
required this.pet});
static List<Person> allPersonFromJson(String jsonData) {
List<Person> person = [];
json.decode(jsonData)['person'].forEach((data) => person.add(_mapPerson(data)));
return person;
}
static Person _mapPerson(Map<String, dynamic> map){
final user_id = map['user_id'] as int?; //required but nullable int with exception
if (user_id == null) {throw UnsupportedError('Invalid data: $map -> "id" is missing');}
final user_name = map['user_name'] as String?; //required but nullable String with exception
if (user_name == null) {throw UnsupportedError('Invalid data: $map -> "name" is missing');}
final user_dob = map['user_dob'] as int;
final pet = Pet.allPetFromJson(map['pets']);
return new Person(
user_id: user_id,
user_name: user_name,
user_dob: user_dob,
pet: pet
);
}
Map<String, dynamic> toJson() {
return {
'user_id': user_id,
'user_name': user_name,
'user_dob': user_dob,
'pet': pet
};
}
}
class Pet{
final int id;
final String name;
final String type;
final List<String> attribute;
Pet ({
required this.id,
required this.name,
required this.type,
required this.attribute});
static List<Pet> allPetFromJson(String jsonData) {
List<Pet> pet = [];
json.decode(jsonData)['person']['pets'].forEach((data) => pet.add(_mapPet(data)));
return pet;
}
static Pet _mapPet(Map<String, dynamic> map){
final id = map['id'] as int?; //required but nullable int with exception
if (id == null) {throw UnsupportedError('Invalid data: $map -> "pet id" is missing');}
final name = map['name'] as String?; //required but nullable String with exception
if (name == null) {throw UnsupportedError('Invalid data: $map -> "pet name" is missing');}
final type = map['type'] as String?; //required but nullable String with exception
if (type == null) {throw UnsupportedError('Invalid data: $map -> "pet type" is missing');}
final attribute = List<String>.from(map['attribute']);
return new Pet(
id: id,
name: name,
type: type,
attribute: attribute
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'type': type,
'attribute': attribute
};
}
}
I am able to call and print the Pet information by directly access to Pet object without include it in Person Object. But what I want to do is try call and print the Pet Object via Person Object. However I get the error "type 'List' is not a subtype of type 'String'".
How can I do that for this case?
I dont know what do allPersonFromJson method but you need to parse String to Json to access data:
final json = await json.decode(string); // <-- in your case "jsonData"
And with json["person"] you have a List of persons ( List<dynamic> )

Parsing a List of Objects in Flutter error

I am using code generation to help with working with JSON files. I am wanting to parse a list of objects, but I keep getting the error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
The Json file I want to deserialize (I've already created models files for the json):
[
{
"id": "Nebula",
"setCount": "5 - 3",
"characters": {
"char1": "mario",
"char2": "peach"
},
"notes": "this player has really cool combos and float cancel nairs are cool"
},
{
"id": "Kambo",
"setCount": "2 - 8",
"characters": {
"char1": "fox",
"char2": ""
},
"notes": "I play fox for fun lmao"
},
{
"id": "Quiet",
"setCount": "8 - 3",
"characters": {
"char1": "zero_suit_samus",
"char2": "wolf"
},
"notes": "this player has really cool combos and float cancel nairs are cool"
}
]
I am not sure what I am doing wrong. Here is the where I call to receive a Playlist from the Json:
void setupHomePage() async {
PlayerList playerList = await getPlayerList();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => Home(),
settings: RouteSettings(
arguments: playerList,
),
),
);
}
Decoding the JSON:
PlayerList playerList;
Future<String> _loadPlayerListAsset () async {
return await rootBundle.loadString('assets/nebula.json');
}
Future loadPlayerList () async {
String jsonString = await _loadPlayerListAsset();
final jsonResponse = jsonDecode(jsonString);
playerList = PlayerList.fromJson(jsonResponse);
}
Future<PlayerList> getPlayerList() async {
await loadPlayerList();
print(playerList.toString());
return playerList;
}
Generated JSON code:
#JsonSerializable(explicitToJson: true)
class PlayerList {
PlayerList (
this.players
);
List<Player> players;
factory PlayerList.fromJson (Map<String, dynamic> json) => _$PlayerListFromJson(json);
Map<String, dynamic> toJson() => _$PlayerListToJson(this);
}
PlayerList _$PlayerListFromJson(Map<String, dynamic> json) {
return PlayerList(
(json['players'] as List)
?.map((e) =>
e == null ? null : Player.fromJson(e as Map<String, dynamic>))
?.toList(),
);
}
Map<String, dynamic> _$PlayerListToJson(PlayerList instance) =>
<String, dynamic>{
'players': instance.players?.map((e) => e?.toJson())?.toList(),
};
The type of jsonResponse here:
final jsonResponse = jsonDecode(jsonString);
Is List since your JSON defines a list of maps.
But then you are doing:
playerList = PlayerList.fromJson(jsonResponse);
...
factory PlayerList.fromJson (Map<String, dynamic> json) => _$PlayerListFromJson(json);
The signature of your fromJson are saying it takes a Map<String, dynamic> which are not compatible with List.
The next problem will be json['players'] which are not going to work since your JSON does not contain any key with the name players. Also, your JSON are a List so it makes no sense.
Example on how to parse the provided JSON
I have make the following code which can parse the JSON you have provided as example:
import 'dart:convert';
class Player {
String id;
String setCount;
Map<String, String> characters;
String notes;
Player.fromJson(Map<String, dynamic> json)
: id = json['id'] as String,
setCount = json['setCount'] as String,
characters = (json['characters'] as Map).cast<String, String>(),
notes = json['notes'] as String;
static List<Player> getPlayersFromJson(List<dynamic> json) =>
json.cast<Map<String, dynamic>>().map((j) => Player.fromJson(j)).toList();
Map<String, dynamic> toJson() => <String, dynamic>{
'id': id,
'setCount': setCount,
'characters': characters,
'notes': notes
};
}
void main() {
const jsonString = '''
[
{
"id": "Nebula",
"setCount": "5 - 3",
"characters": {
"char1": "mario",
"char2": "peach"
},
"notes": "this player has really cool combos and float cancel nairs are cool"
},
{
"id": "Kambo",
"setCount": "2 - 8",
"characters": {
"char1": "fox",
"char2": ""
},
"notes": "I play fox for fun lmao"
},
{
"id": "Quiet",
"setCount": "8 - 3",
"characters": {
"char1": "zero_suit_samus",
"char2": "wolf"
},
"notes": "this player has really cool combos and float cancel nairs are cool"
}
]
''';
final playerList = Player.getPlayersFromJson(json.decode(jsonString) as List);
playerList.forEach((player) => print('${player.id} | ${player.notes}'));
// Nebula | this player has really cool combos and float cancel nairs are cool
// Kambo | I play fox for fun lmao
// Quiet | this player has really cool combos and float cancel nairs are cool
print(json.encode(playerList));
}

How to get json array in Flutter/Dart

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).