I'm trying to create a custom json and with android java I can use json object and json array, but I couldn't find them in flutter. I created list <Map <String, String >> but when I add data it changes all indexes.
List<Map<String,String>> myList=[];
Map<String,String> mymap;
for(int i=0;i<5;i++){
mymap['name']='test'+i.toString();
myList.add(mymap);
print(myList[0]);// its always change test0,test1,test2
}
for (int i=0;i<5;i++){
print(myList[i]); // its write test5,test5,test5,test5,test5 why?
}
//pass your decoded json
Map<String, dynamic> json = jsonDecode(rawJson);
List<Location> locations = List<Location>.from(json["locations"].map((x) => Location.fromJson(x)))
//Location class => days is a premitive list and can be deserialized below
class Location {
Location({
this.name,
this.days,
});
String name;
List<int> days;
factory Location.fromJson(Map<String, dynamic> json) => Location(
name: json["name"],
days: List<int>.from(json["days"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"name": name,
"days": List<dynamic>.from(days.map((x) => x)),
};
}
When you assign variable to complex class it is passing reference not value, complex classes are those that you created and built in like List, Map ... etc
In this example in your List you are adding same Map 5 times,
and because it was passing reference same Map getting changed 5 times. I hope I make sense.
Here an example.
List<Map<String,String>> myList=[];
Map<String,String> mymap; // This created one object in the current scope.
// First iteration , i = 0
mymap['name']='test'+i.toString(); // Now mymap = { name: 'test0' };
myList.add(mymap); // mylist = [mymap];
// Second iteration , i = 1
mymap['name'] = 'test'+i.toString(); // Now mymap = { name: 'test1' };. But since you already added the same mymap in myList, now myList = [{ name: 'test1' }
myList.add(mymap); // This is again adding the same mymap. So mylist = [{ name: 'test1' }, { name: 'test1' }];
Related
Trying to create an if statement that checks if an API returns 'items' containing data
Here is the API url, you can see that items is empty for that specific data query https://data.food.gov.uk/food-alerts/id?since=2021-01-04T00:00:00Z
My code is below, been trying to see if I can check 'items' to see if it is null, as well as checking for its length and see if it equals 0 but has not worked so far
class AllergyAlert {
final String title;
AllergyAlert({this.title});
factory AllergyAlert.fromJson(Map<String, dynamic> json) {
if (json['items'] == null) {
return AllergyAlert(
title: 'No new allergy alerts',
);
} else {
return AllergyAlert(
title: json['items'][0]['title'],
);
}
}
}
You can try this
return AllergyAlert(
title: json['items'].isEmpty ? 'No new allergy alerts' : json['items'][0]['title'],
);
First create a class to decode your json string with. You can paste your json here Quicktype
This can then be used with a FutureBuilder to load the data. Here is a full example
Solution
Then after that you will just use the defined names to check. Like:
class Allergen {
Allergen({
this.meta,
this.items,
});
final Meta meta;
final List<dynamic> items;
factory Allergen.fromJson(Map<String, dynamic> json) => Allergen(
meta: Meta.fromJson(json["meta"]),
items: List<dynamic>.from(json["items"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"meta": meta.toJson(),
"items": List<dynamic>.from(items.map((x) => x)),
};
}
class Meta {
Meta({...//more here
you can just check the length of the list
Allergen.items.length==0?//Do This://Else This
I have a Nested Object like this just a bit bigger:
"name": "String",
"exercise": [
{
"index": 1,
}
],
"pause": [
{"index":2},
]
I convert the exercise and pause to a Json String and save them in a column in SQFLite.
The problem
When I read the Data everything works fine including the List (not nested) but both list's of nested Object are empty when I read a value of the nested object it gives an error.
item.exercise[0].index.toString()
Valid Value range is empty: 0
When I read only item.exercise.toString() it returns []. Without != null ? [...] : List<Exercise>() it also throws an error
Data I get from my Database (shortened)
List of:
[{name: number 1, id: 56, exercise: [{"index":1,"weightGoal":[15,16,17]}, {"index":3,"weightGoal":[15,16,17]}], pause: [{"index":2}]},{"index":4}]}]
What I do with it
Here I try to go through the list and convert it into a List of PlanModel:
List<PlanModel> list =
res.isNotEmpty ? res.map((c) => PlanModel.fromJson(c)).toList() : [];
return list;
Full model
PlanModel planModelFromJson(String str) => PlanModel.fromJson(json.decode(str));
String planModelToJson(PlanModel data) => json.encode(data.toJson());
class PlanModel {
PlanModel({
this.name,
this.id,
this.workoutDays,
this.pastId,
this.timesDone,
this.exercise,
this.pause,
});
String name;
int id;
List<String> workoutDays;
int pastId;
int timesDone;
List<Exercise> exercise;
List<Pause> pause;
factory PlanModel.fromJson(Map<String, dynamic> json) => PlanModel(
name: json["name"],
id: json["id"],
workoutDays: List<String>.from(jsonDecode(json["workoutDays"])),
pastId: json["pastId"],
timesDone: json["timesDone"],
exercise: json["Exercise"] != null ? new List<Exercise>.from(json["Exercise"].map((x) => Exercise.fromJson(x))): List<Exercise>(),
pause: json["Pause"] != null ? new List<Pause>.from(json["Pause"].map((x) => Pause.fromJson(x))): List<Pause>(),
);
Map<String, dynamic> toJson() => {
"name": name,
"id": id,
"workoutDays": List<dynamic>.from(workoutDays.map((x) => x)),
"pastId": pastId,
"timesDone": timesDone,
"Exercise": List<dynamic>.from(exercise.map((x) => x.toJson())),
"Pause": List<dynamic>.from(pause.map((x) => x.toJson())),
};
}
class Exercise {
Exercise({
this.index,
this.name,
this.goal,
this.repGoal,
this.weightGoal,
this.timeGoal,
this.setGoal,
});
int index;
String name;
int goal;
int repGoal;
List<int> weightGoal;
int timeGoal;
List<String> setGoal;
Exercise.fromJson(dynamic json) {
// anything that is wrapped around with this [] in json is converted as list
// anything that is wrapped around with this {} is map
index = json["index"];
name = json["name"];
goal = json["goal"];
repGoal = json["repGoal"];
weightGoal = json["weightGoal"] != null ? json["weightGoal"].cast<int>() : [];
timeGoal = json["timeGoal"];
setGoal = json["setGoal"] != null ? json["setGoal"].cast<String>() : [];
}
Map<String, dynamic> toJson() => {
"index": index,
"name": name,
"goal": goal,
"repGoal": repGoal,
"weightGoal": List<dynamic>.from(weightGoal.map((x) => x)),
"timeGoal": timeGoal,
"setGoal": List<dynamic>.from(setGoal.map((x) => x)),
};
}
class Pause {
Pause({
this.index,
this.timeInMilSec,
});
int index;
int timeInMilSec;
factory Pause.fromJson(Map<String, dynamic> json) => Pause(
index: json["index"],
timeInMilSec: json["timeInMilSec"],
);
Map<String, dynamic> toJson() => {
"index": index,
"timeInMilSec": timeInMilSec,
};
}
Read this first.
You need to tweek this code a little to work for you but the idea is that;
also read comment in the code.
if json string comes with [] those around, json.decode will decode it as List<Map>.
if it comes with {} this json.decode will decode it as Map.
note: be careful while using generics on json.decode I reccommend not to.
data inside the jsonString does not really corresponds with the values inside the fromJson function. json string which you have provided was not really good. so I think you will understand how to manipulate it for your needs.
also main constructor Exercise you can use for initial data.
import 'dart:convert';
class Exercise{
Exercise({this.index,
this.name,
this.repGoal,
this.weightGoal,
this.setGoal});
String index;
String name;
String repGoal;
String weightGoal;
String setGoal;
Exercise.fromJson(dynamic json) :
// anything that is wrapped around with this [] in json is converted as list
// anything that is wrapped around with this {} is map
index = json["exercise"][0]["index"].toString(),
name = json["name"].toString(),
repGoal = json["repGoal"].toString(),
weightGoal = json["weightGoal"].toString(),
setGoal = json["setGoal"].toString();
}
void main(){
String jsonString = '{name: number 1, id: 56, exercise: [{"index":1,"weightGoal":[15,16,17], pause: [{"index":2}]}';
Map json = json.decode(jsonString);
Exercise.fromJson(json);
}
I found it out :)
I have restructured my fromJson to this, especially the jsonDecode was important, because json["exercise "] was only a String.
PlanModel.fromJson(dynamic json) {
name = json["name"];
if (json["exercise"] != null) {
exercise = [];
jsonDecode(json["exercise"]).forEach((v) {
exercise.add(Exercise.fromJson(v));
});
}}
now I can access it with
PlanModel item = snapshot.data[index];
item.exercise[0].timeGoal.toString()
I have objects that will filled by a user in a form. I parse these objects to json and add that json in a list to pass in body of request. But i cant do this.
incrementListPaymentSlipes(PaymentSlipes objPayment) async {
objPayment.name = "Douglas";
objPayment.personalId = "00000000000";
Map<String, dynamic> json = objPayment.toJson();
listPaymentSlipes.add(jsonEncode(json));
}
var response = await http.post(url, body: {
"payment_slips": listPaymentSlipes,
}
example of correct body:
"payment_slips": [
{
"personal_id": "01888728680",
"name": "Fulano da Silva"
}
]
{"error":"'{{personal_id: 00000000000, name: Douglas}}' é invalido como 'payment_slips'","code":"payment_slips_invalid"}```
You can do it in a very simple way. Create payment.dart file and copy paste the below code classes.
class PaymentList {
PaymentList(this.payments);
List<Payment> payments;
Map<String, dynamic> toJson() => <String, dynamic>{
'payment_slips': payments,
};
}
class Payment {
Payment({this.name, this.personalId});
String name;
String personalId;
Map<String, dynamic> toJson() => <String, dynamic>{
'personal_id': personalId,
'name': name,
};
}
Now you can covert it to the required json format using below code. For example I am creating a dummy list:
final PaymentList paymentList =
PaymentList(List<Payment>.generate(2, (int index) {
return Payment(name: 'Person $index', personalId: '$index');
}));
final String requestBody = json.encoder.convert(paymentList);
The requestBody variable will have the json string as follows:
{"payment_slips": [
{
"personal_id": "0",
"name": "Person 0"
},
{
"personal_id": "1",
"name": "Person 1"
}
]}
Now you can call the api:
var response = await http.post(url, body: requestBody}
Note: Please import the below package, which will be required to access json:
import 'dart:convert';
So it looks like you are not getting the JSON you expect. I have put together some code to show you how to get the body you want.
Link to run in DartPad https://dartpad.dartlang.org/3fde03078e56efe13d31482dea8e5eef
class PaymentSlipes {
String name;
String personaId;
ObjPayment({this.name, this.personaId});
//You create this to convert your object to JSON
Map<String, dynamic> toJson() => {'name': name, 'personaId': personaId};
}
// This method is needed to convert the list of ObjPayment into an Json Array
List encondeToJson(List<PaymentSlipes> list) {
List jsonList = List();
list.map((item) => jsonList.add(item.toJson())).toList();
return jsonList;
}
// This is an example and this code will run in DartPad link above
void main() {
PaymentSlipes objPayment = PaymentSlipes(name: "Douglas", personaId: "123425465");
PaymentSlipes objPayment2 = PaymentSlipes(name: "Dave", personaId: "123425465;
PaymentSlipes objPayment3 = PaymentSlipes(name: "Mike", personaId: "123425465");
var list = [objPayment, objPayment2, objPayment3];
// This is the mapping of the list under the key payment_slips as per your example and the body i would pass to the POST
var finalJson = {"payment_slips": encondeToJson(list)};
print(finalJson);
}
i have class that generate json list this is my class
class Tool{
String Name;
bool selection;
String englishName;
Map<String, dynamic> toJson() {
return {
'Name': persianName,
'selection': selection,
'englishName': englishName
};
}
}
List<Tool> tools=new List();
setTool(tool){
tools.add(tool);
}
toolsLength(){
return tools.length;
}
updatetool(index,goal){
tools[index]=goal;
}
getTool(index){
return tools[index];
}
getAllTools(){
return tools;
}
and this is dio library that send my list to server every thing is ok but my array is into Double quotation in other word my list is string how to pick up double quotation around of json array . if assume my json array hase
"tools": [{"name":"jack","selection" : false " ,"englishName":"jock"}]
result is :
"tools": "[{"name":"jack","selection" : false " ,"englishName":"jock"}]"
how fix it this is my class for send
FormData formData = new FormData.from({
"tools":jsonEncode(getAllTools().map((e) => e.toJson()).toList()) ,
});
response = await
dio.post("${strings.baseurl}/analyze/$username/$teacher", data:
formData);
print("----------> response is :"+response.toString());
Edit
You can paste the following code to DarPad https://dartpad.dartlang.org/
The following demo shows transform your Json String to Tool List and Convert your Tool List to JSON string again and use map.toJson
var yourresult = toolList.map((e) => e.toJson()).toList();
you can see result in picture
use FormData.from need to know what your api's correct JSON String.
Please test your web api with Postman, if you success, you will know correct format string.
In your code
FormData formData = new FormData.from({
"tools":jsonEncode(getAllTools().map((e) => e.toJson()).toList()) ,
});
if you are trying to to do
FormData formData = new FormData.from({
"tools":'[{"name":"jack","selection" : false ,"englishName":"jock"}, {"name":"jack2","selection" : false ,"englishName":"jock2"}]' ,
});
so you can get your json string first and put it in FormData
var toolsJson = toolsToJson(toolList);
FormData formData = new FormData.from({
"tools":toolsJson ,
});
full demo code, you can paste to DartPad to see string and list conversion
import 'dart:async';
import 'dart:io';
import 'dart:core';
import 'dart:convert';
class Tools {
String name;
bool selection;
String englishName;
Tools({
this.name,
this.selection,
this.englishName,
});
factory Tools.fromJson(Map<String, dynamic> json) => new Tools(
name: json["name"],
selection: json["selection"],
englishName: json["englishName"],
);
Map<String, dynamic> toJson() => {
"name": name,
"selection": selection,
"englishName": englishName,
};
}
main() {
List<Tools> toolsFromJson(String str) => new List<Tools>.from(json.decode(str).map((x) => Tools.fromJson(x)));
String toolsToJson(List<Tools> data) => json.encode(new List<dynamic>.from(data.map((x) => x.toJson())));
var toolsStr = '[{"name":"jack","selection" : false ,"englishName":"jock"}, {"name":"jack2","selection" : false ,"englishName":"jock2"}]';
var toolList = toolsFromJson(toolsStr);
var toolsJson = toolsToJson(toolList);
print("toolsJson ${toolsJson} \n");
var toolsmap = toolList[0].toJson();
print("toolsmap ${toolsmap.toString()}\n");
var yourresult = toolList.map((e) => e.toJson()).toList();
print(yourresult.toString());
}
you can paste your JSON string to https://app.quicktype.io/, you will get correct Dart class
correct JSON string of your sample. in false keyword followed by a " cause JSON string parsing error.
[
{"name":"jack",
"selection" : false ,
"englishName":"jock"
}
]
code to parse JSON string and encode to List, use toJson will convert to JSON string you need to send with dio form
// To parse this JSON data, do
//
// final tools = toolsFromJson(jsonString);
import 'dart:convert';
List<Tools> toolsFromJson(String str) => new List<Tools>.from(json.decode(str).map((x) => Tools.fromJson(x)));
String toolsToJson(List<Tools> data) => json.encode(new List<dynamic>.from(data.map((x) => x.toJson())));
class Tools {
String name;
bool selection;
String englishName;
Tools({
this.name,
this.selection,
this.englishName,
});
factory Tools.fromJson(Map<String, dynamic> json) => new Tools(
name: json["name"],
selection: json["selection"],
englishName: json["englishName"],
);
Map<String, dynamic> toJson() => {
"name": name,
"selection": selection,
"englishName": englishName,
};
}
I am trying to work with firebase database from flutter. I have made a model class which I am converting to json and from json via plugin json_serializable. Where model class works perfectly fine with hard coded json data but when I am trying to save the encoded data to firebase database it's getting saved as a string instead of key value pair in firebase database.Below is my code to convert it and save it
List<Action> actions = [];
actions.add(new Action('This is label', 'mranuran.com'));
EgluCard egluCard = new EgluCard(true, true, "HI", "World", "Awesome",CardType.TYPE_1 , ["images"], 123, 125, "#FFFFFF", PlatformType.IOS, actions);
//print(json.encode(egluCard));
// var jsonString = '{"isInternal":true,"isPublished":true,"title":"HI","body":"World","caption":"Awesome","cardType":"TYPE_1","images":["images"],"expiry":123,"showAt":125,"bgColor":"#FFFFFF","platformType":"IOS","actions":[{"label":"This is label","url":"mranuran.com"}]}';
// Map<String,dynamic> cardMap = json.decode(jsonString);
// EgluCard egluCard = EgluCard.fromJson(cardMap);
// print(egluCard.actions[0].label);
var jsonString = json.encode(egluCard);
var trimmedString = jsonString.substring(0,jsonString.length);
print(trimmedString);
cardsDBRef.push().set(jsonString)
.then((_){
print('saved!!');
});
when I am printing the json.encode(eGluCard) then it's printing a valid json but when it's getting saved into firebase I am getting the following from firebase. It was supposed to save as key value pair but it was saved as a whole string.
"{\"isInternal\":true,\"isPublished\":true,\"title\":\"HI\",\"body\":\"World\",\"caption\":\"Awesome\",\"cardType\":\"TYPE_1\",\"images\":[\"images\"],\"expiry\":123,\"showAt\":125,\"bgColor\":\"#FFFFFF\",\"platformType\":\"IOS\",\"actions\":[{\"label\":\"This is label\",\"url\":\"mranuran.com\"}]}"
what can be wrong in this approach? below are my model classed and their generated serializer respectively
EgluCard.dart
import 'card_type.dart';
import 'platform_type.dart';
import 'action.dart';
import 'package:json_annotation/json_annotation.dart';
part 'eglu_card.g.dart';
#JsonSerializable()
class EgluCard {
bool isInternal;
bool isPublished;
String title;
String body;
String caption;
CardType cardType;
List<String> images;
int expiry;
int showAt;
String bgColor;
PlatformType platformType;
List<Action> actions;
EgluCard(this.isInternal,this.isPublished,this.title,this.body,this.caption,this.cardType,this.images,
this.expiry,this.showAt,this.bgColor,this.platformType,this.actions);
factory EgluCard.fromJson(Map<String, dynamic> json) => _$EgluCardFromJson(json);
Map<String, dynamic> toJson() => _$EgluCardToJson(this);
}
EgluCard Serializer
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'eglu_card.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
EgluCard _$EgluCardFromJson(Map<String, dynamic> json) {
return EgluCard(
json['isInternal'] as bool,
json['isPublished'] as bool,
json['title'] as String,
json['body'] as String,
json['caption'] as String,
_$enumDecodeNullable(_$CardTypeEnumMap, json['cardType']),
(json['images'] as List)?.map((e) => e as String)?.toList(),
json['expiry'] as int,
json['showAt'] as int,
json['bgColor'] as String,
_$enumDecodeNullable(_$PlatformTypeEnumMap, json['platformType']),
(json['actions'] as List)
?.map((e) =>
e == null ? null : Action.fromJson(e as Map<String, dynamic>))
?.toList());
}
Map<String, dynamic> _$EgluCardToJson(EgluCard instance) => <String, dynamic>{
'isInternal': instance.isInternal,
'isPublished': instance.isPublished,
'title': instance.title,
'body': instance.body,
'caption': instance.caption,
'cardType': _$CardTypeEnumMap[instance.cardType],
'images': instance.images,
'expiry': instance.expiry,
'showAt': instance.showAt,
'bgColor': instance.bgColor,
'platformType': _$PlatformTypeEnumMap[instance.platformType],
'actions': instance.actions
};
T _$enumDecode<T>(Map<T, dynamic> enumValues, dynamic source) {
if (source == null) {
throw ArgumentError('A value must be provided. Supported values: '
'${enumValues.values.join(', ')}');
}
return enumValues.entries
.singleWhere((e) => e.value == source,
orElse: () => throw ArgumentError(
'`$source` is not one of the supported values: '
'${enumValues.values.join(', ')}'))
.key;
}
T _$enumDecodeNullable<T>(Map<T, dynamic> enumValues, dynamic source) {
if (source == null) {
return null;
}
return _$enumDecode<T>(enumValues, source);
}
const _$CardTypeEnumMap = <CardType, dynamic>{CardType.TYPE_1: 'TYPE_1'};
const _$PlatformTypeEnumMap = <PlatformType, dynamic>{
PlatformType.ANDROID: 'ANDROID',
PlatformType.IOS: 'IOS',
PlatformType.ANDROID_THING: 'ANDROID_THING',
PlatformType.ANY: 'ANY'
};
Action.dart
import 'package:json_annotation/json_annotation.dart';
part 'action.g.dart';
#JsonSerializable()
class Action {
String label;
String url;
Action(this.label,this.url);
factory Action.fromJson(Map<String, dynamic> json) => _$ActionFromJson(json);
Map<String, dynamic> toJson() => _$ActionToJson(this);
}
Action Serializer
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'action.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Action _$ActionFromJson(Map<String, dynamic> json) {
return Action(json['label'] as String, json['url'] as String);
}
Map<String, dynamic> _$ActionToJson(Action instance) =>
<String, dynamic>{'label': instance.label, 'url': instance.url};
PlatformType and CardType are enums
Okay turns out I have to decode and encoded string before passing it to firebase.
So code to save the model class to firebase will be like this:
List<Action> actions = [];
actions.add(new Action('This is label', 'mranuran.com'));
EgluCard egluCard = new EgluCard(true, true, "HI", "World", "Awesome",CardType.TYPE_1 , ["images"], 123, 125, "#FFFFFF", PlatformType.IOS, actions);
var jsonString = json.encode(egluCard);
print(json.decode(jsonString));
cardsDBRef.push().set(json.decode(jsonString))
.then((_){
print('saved!!');
});