How can put a Set of object to Json. Seems like that code is not good at all
Future<File> writeBasket(Set<Item> listItems) async {
final file = await _localFile;
var jsonString = listItems.map((Item item) {
return jsonEncode(item);
});
return file.writeAsString(jsonString.toString());
}
Make sure that Item has a toJson method, for example:
class Item {
String val1;
Item(this.val1);
Map<String, dynamic> toJson() => {'val1': val1};
}
The nearest equivalent to a set in json is a list, so convert your set to a list before calling json.encode.
Set<Item> items = Set<Item>()..add(Item('xxx'))..add(Item('yyy'));
String j = json.encode(items.toList());
print(j);
prints [{"val1":"xxx"},{"val1":"yyy"}] which you could save to your file.
Related
Trying to save a list in shared sharedpreferences by converting to JsonString. But repeatedly getting the encodable object failed : Instance of 'CustonContact'. Help out
class CustomContact extends Contact{
Contact contact;
bool isChecked;
CustomContact({
this.contact,
this.isChecked = false,
});
Map toJson() {
return {
'contact': contact,
'isChecked': isChecked,
};
}
CustomContact.fromJson(Map<String, dynamic> json)
: contact = json['contact'],
isChecked = json['isChecked'];
}
****Trying to call it in here to save in sharedpreference****
_saveTrustedContactsNames() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
List<CustomContact> _contactsSelectedNames = [];
for (var _customContact in contactsSelected) { **contactsSelected is already populated**
setState(() {
_contactsSelectedNames.add(_customContact);
});
}
**trying to convert to JsonString**
String _trustedContactsJson = jsonEncode(_contactsSelectedNames);
print(_trustedContactsJson);
preferences.setString('_contactstrusted', _trustedContactsJson);
}
That's cause sharedPreferences can't automatically convert Contact to json. You'll need to create a toJson method in Contact and pass that method in to your CustomContact's toJson method and vice versa for the fromJson.
Map toJson() {
return {
'contact': contact.toJson(),
'isChecked': isChecked,
};
}
CustomContact.fromJson(Map<String, dynamic> json)
: contact = Contact.fromJson(json['contact']),
isChecked = json['isChecked'];
I want to send a List of ManageTagModel in a multipart request along with other models and files..
I am not certain of how to send this List of model..
This is my code for sending the multipart request without the List:
var uri = Uri.parse(...);
final request = http.MultipartRequest('Post', uri);
request.fields['Id'] = '3';
request.fields['Name'] = siteModel.name;
request.fields['MapAddress'] = siteModel.mapAddress;
request.fields['Country'] = siteModel.country;
request.fields['City'] = siteModel.city;
request.fields['CategoryNb'] = siteModel.categoryNb;
request.fields['UserId'] = userId;
request.fields['Caption'] = caption;
for (File i in
multipleFiles) {
final mimeTypeData =
lookupMimeType(i.path, headerBytes: [0xFF, 0xD8]).split('/');
print("IMAGE: " + i.path);
// Attach the file in the request
final file = await http.MultipartFile.fromPath('files', i.path);
print(mimeTypeData[0] + " mimeTypeData[0]");
print(mimeTypeData[1] + " mimeTypeData[1]");
request.files.add(file);
this is my model:
import 'dart:convert';
class ManageTagModel {
String posX;
String posY;
String postOrder;
String tagger;
String tagged;
ManageTagModel(
{this.posX, this.posY, this.postOrder, this.tagger, this.tagged});
//Flutter way of creating a constructor
factory ManageTagModel.fromJson(Map<String, dynamic> json) => ManageTagModel(
posX: json['PosX'],
posY: json['PosY'],
postOrder: json['PostOrder'],
tagged: json['Tagged'],
tagger: json['Tagger']);
Map<String, dynamic> toMap() {
return {
"PosX": posX,
"PosY": posY,
"PostOrder": postOrder,
"Tagger": tagger,
"Tagged": tagged
};
}
}
List<ManageTagModel> fromJson(String jsonData) {
// Decode json to extract a map
final data = json.decode(jsonData);
return List<ManageTagModel>.from(
data.map((item) => ManageTagModel.fromJson(item)));
}
String toJson(ManageTagModel data) {
// First we convert the object to a map
final jsonData = data.toMap();
// Then we encode the map as a JSON string
return json.encode(jsonData);
}
List encodeToJson(List<ManageTagModel> list) {
List jsonList = List();
list.map((item) => jsonList.add(item.toMap())).toList();
return jsonList;
}
My backend c# method has a parameter List
Any help is appreciated!!
I'm pretty sure I'm quite late here and you might have already found a solution. I have gone through multiple threads and didn't actually find any answers but discovered myself out of frustration and thought to myself that the answer actually is still not out there for any other lost human soul. So here is my solution for anyone still stuck here which is quite intuitive.
You simply have to add all the elements of the list to the request as "files" instead of "fields". But instead of fromPath() method, you have to use fromString().
final request = http.MultipartRequest('Post', uri);
List<String> ManageTagModel = ['xx', 'yy', 'zz'];
for (String item in ManageTagModel) {
request.files.add(http.MultipartFile.fromString('manage_tag_model', item));
}
This worked out for me and I hope it works for you too.
if the data was not string
for (int item in _userData['roles']) {
request.files
.add(http.MultipartFile.fromString('roles', item.toString()));
}
Is it possible to deserialize a json with dynamic key but structured values into Map in flutter dart.
I am having a json like
{
"data" : {
"apple":{"qty":5, "price":100},
"orange":{"qty":2, "price":40},
}
}
And I want this to deserialize in flutter/dart to a model class below
class Data {
Map<String, Item> itemMap;
factory Data.fromJson(Map<String,dynamic> json) {
itemMap : json["data"]; //How to parse.
}
}
class Item {
int qty;
int price;
}
I have read through a medium blog and even this also not covering the Map part.
You need to do something like this:
//...
Future<List<ItemModel>> fetchFood() async {
List<ItemModel> foodItemsList = [];
// Get json response and parse it as a Map<String, dynamic>
final response = {
"data" : {
"apple":{"qty":5, "price":100},
"orange":{"qty":2, "price":40},
}
};
// with your real get request use this:
// final parsedJson = json.decode(response.body)['data'];
// Parsed Json have what's inside data, in case of real request look for the line above this.
final parsedJson = response['data'];
// Iterate over all fruits and create Item object from each,
// then push to a list of Item's objects to return it.
parsedJson.forEach((k,v) => foodItemsList.add(ItemModel.fromJson(v)));
return foodItemsList;
}
// Item model
class ItemModel {
int qty;
int price;
ItemModel.fromJson(Map<String,dynamic> parsedJson)
: qty = parsedJson['qty'],
price = parsedJson['price'];
}
// Then call it
main() async {
List<ItemModel> foodItemsList = await fetchFood();
//..
}
If you need the fruit name as part of the object:
//...
Future<List<ItemModel>> fetchFood() async {
List<ItemModel> foodItemsList = [];
// Get json response and parse it as a Map<String, dynamic>
final response = {
"data" : {
"apple":{"qty":5, "price":100},
"orange":{"qty":2, "price":40},
}
};
// with your real get request use this:
// final parsedJson = json.decode(response.body)['data'];
// Parsed Json have what's inside data, in case of real request look for the line above this.
final parsedJson = response['data'];
// Iterate over all fruits and create Item object from each,
// then push to a list of Item's objects to return it.
parsedJson.forEach((fruitName, fruitDetails)
=> foodItemsList.add(
ItemModel.fromJson(fruitName, fruitDetails)
)
);
return foodItemsList;
}
// Item model
class ItemModel {
String name;
int qty;
int price;
ItemModel.fromJson(String fruitName, Map<String,dynamic> parsedJson)
: name = fruitName,
qty = parsedJson['qty'],
price = parsedJson['price'];
}
// Then call it
main() async {
List<ItemModel> foodItemsList = await fetchFood();
print(foodItemsList[1].name); //orange
//..
}
I have a similar JSON with a few changes:
{
"sub_item": {
"491": ["92837|1.3|Pistachio|right", "92838|2.5|Hazelnut|left"],
"427": ["92839|7.05|Almonds|", "92840|5.12|Walnuts|"],
"396": ["92841|15|Saffron|"],
"275": ["92842|45|Caviar|"]
}
}
The keys of sub_item map (491, 427, 396, 275, and...) are dynamic(as a label not as a type) and will change per order. For example, it will be 376, 325, 493... in another order.
I want to shows both keys and values on my Flutter app and do not know how to fetch these data and show them separately. Something like this:
491:
£1.30 Pistachio
£2.50 Hazelnut
427:
£7.05 Almonds
£5.12 Walnuts
396:
£15.00 Saffron
275:
£45.00 Caviar
I used this code and it worked for me somehow but it shows only the first item of the lists. for example, it shows only Pistachio for 491 not Hazelnut and the same it shows only Almonds for 427 not Walnuts:
Future<List<ItemModel>> fetchFood() async {
List<ItemModel> foodItemsList = [];
final response = {
"sub_item": {
"491": ["92837|1.3|Pistachio|right", "92838|2.5|Hazelnut|left"],
"427": ["92839|7.05|Almonds|", "92840|5.12|Walnuts|"],
"396": ["92841|15|Saffron|"],
"275": ["92842|45|Caviar|"]
}
};
final parsedJson = response['sub_item'];
parsedJson.forEach((fruitName, fruitDetails) =>
foodItemsList.add(ItemModel.fromJson(fruitName, fruitDetails)));
return foodItemsList;
}
// Item model
class ItemModel {
String id;
String details;
ItemModel.fromJson(String subItemID, List<dynamic> subItemDetails)
: id = subItemID,
details = subItemDetails[0];
}
// Then call it
mainTest() async {
List<ItemModel> foodItemsList = await fetchFood();
for (var i = 0, j = 0;
i < foodItemsList.length;
j < foodItemsList[i].details.length, i++, j++) {
print(foodItemsList[i].id);
print(foodItemsList[j].details.split('|')[2]);
}
}
The console result:
flutter: 491
flutter: Pistachio
flutter: 427
flutter: Almonds
flutter: 396
flutter: Saffron
flutter: 275
flutter: Caviar
I found a way to achieve it. We can convert the Map from one type to another.
class Data {
Map<String, Item> itemMap;
factory Data.fromJson(Map<String,dynamic> json) {
itemMap : getMapDataFrom(json["data"]); //How to parse.
}
static Map<String, Item> getFruitItemMap(Map<String, dynamic> map) {
final Map<String, Item> fruitItemMap = HashMap();
map.forEach((name, value) {
bitItemLites[name] = Item.fromJson(value, name);
});
return bitItemLites;
}
}
class Item {
int qty;
int price;
factory Item.fromJson(Map<String,dynamic> json) {
return Item(json['qty'], json['price']);
}
}
I have a JSON string, inside of it I have an array, I want to add data to it as I tried to do it below:
String myJSON = '{"listOfSubtasks":["dasd","dadd","dadsd"]}';
arrayToStringAndBack(addElement) async {
var json = jsonDecode(myJSON);
var getArray = json['listOfSubtasks']; //returns [dasd,dadd,dadsd]
setState(() {
getArray.add(addElement);
});
// as I want to push it to a db I convert [dasd,dadd,dadsd] to a String ["dasd","dadd","dadsd"]
String arrayToString = jsonEncode(getArray);
print(arrayToString);
}
...
textfieldform
- onSaved: (val) {
subtasks = val;
arrayToStringAndBack(val);
},
...
When I type smth and click on a submit button an element is added to the end of an array but once I try to do it one more time, to add an element, the last element that was added changes to one I created.
I want to add as many elements as I want, not just a single one
Solved
var arrayOfSubTasks = [];
arrayToStringAndBack(addElement, arr) async {
var json = jsonDecode(myJSON);
var getArray = json['listOfSubtasks'];
setState(() {
getArray.add(arr);
});
String arrayToString = jsonEncode(getArray);
print(arrayToString);
}
...
onSaved: (val) {
subtasks = val;
setState(() {
arrayOfSubTasks.add(val);
});
arrayToStringAndBack(val, arrayOfSubTasks);
},
You can treat your list of subtasks as a List to be able to add String with List.add(). Then encode the List to a json with jsonEncode()
I'm trying out things with Flutter right now. But my variables keep getting reinitialised when accessed from another class.
I'm using json parsing and i need two parts of my request. The "Relatorio" part and the "Mensagem" part.
to parse this json i'm doing this:
List<RelatorioProdutos> parseRelatorioPorProduto(String responseBody) {
final parsed = json.decode(responseBody);
var relatorio = parsed['Relatorio'];
var mensagem = parsed['Mensagem'];
print (mensagem); // Here the variable returns well,
//but when i need it in other class i receive null.
return relatorio.map<RelatorioProdutos>((json) => new RelatorioProdutos.fromJson(json)).toList();
}
class RelatorioProdutos {
String CodigoProduto;
var QtdVendida;
var TotalVendas;
String Descricao;
RelatorioProdutos({this.CodigoProduto, this.QtdVendida, this.TotalVendas, this.Descricao,});
factory RelatorioProdutos.fromJson(Map json) {
//returns a List of Maps
return new RelatorioProdutos(
CodigoProduto: json['CodigoProduto'] as String,
QtdVendida: json['QtdVendida'],
TotalVendas: json['TotalVendas'],
Descricao: json['Descricao'] as String,
);
}
}
I want to use this 'mensagem' variable in another class to show the error for user, but i always receive 'null'.
i already tried setState but it reloads my json and i dont want to request the RestServer again.
Thanks from now!
If I understand correctly, you want to access a local variable of a function from another class. I don't think it's possible.
One way to do it, would be to wrap your response in another object containing the response, and this variable:
List<Response<RelatorioProdutos>> parseRelatorioPorProduto(
String responseBody) {
final parsed = json.decode(responseBody);
var relatorio = parsed['Relatorio'];
var mensagem = parsed['Mensagem'];
print(mensagem); // Here the variable returns well,
//but when i need it in other class i receive null.
return relatorio
.map((json) => new Response<RelatorioProdutos>(
new RelatorioProdutos.fromJson(json), mensagem))
.toList();
}
class RelatorioProdutos {
String CodigoProduto;
var QtdVendida;
var TotalVendas;
String Descricao;
RelatorioProdutos({
this.CodigoProduto,
this.QtdVendida,
this.TotalVendas,
this.Descricao,
});
factory RelatorioProdutos.fromJson(Map json) {
//returns a List of Maps
return new RelatorioProdutos(
CodigoProduto: json['CodigoProduto'] as String,
QtdVendida: json['QtdVendida'],
TotalVendas: json['TotalVendas'],
Descricao: json['Descricao'] as String,
);
}
}
class Response<T> {
const Response(
this.value,
this.errorMessage,
);
final T value;
final String errorMessage;
bool get hasError => errorMessage != null;
}
In this example I created a Response object that can contains both the response value and an error message.
In the parseRelatorioPorProduto, instead of returning the relatorio, I changed the return type to Response<RelatorioProdutos> in order to have access to the value and the error message from any class which call this function.
Thanks Letsar, i tried yout ideia but i get a lot of others erros.
To solve this problem i used this:
List<RelatorioProdutos> parseRelatorioPorProduto(String responseBody) {
final parsed = json.decode(responseBody);
var relatorio = parsed['Relatorio'];
var mensagem = parsed['Mensagem'];
if(mensagem[0].toString().substring(16,17) == "0"){
List<RelatorioProdutos> asd = new List();
RelatorioProdutos aimeudeus = new RelatorioProdutos(Descricao: mensagem[0].toString(), CodigoProduto: "a", TotalVendas: 0, QtdVendida: 0);
asd.add(aimeudeus);
return asd;
}else{
return relatorio.map<RelatorioProdutos>((json) => new RelatorioProdutos.fromJson(json)).toList();
}
}