My goal is to insert a map key as an id inside map value (which is also a map, the nested one).
Say I have a map as follows
Map<String, dynamic> userMap = {
"id_1" : {
"name": "John",
"surname": "Doe",
"age": 25,
},
"id_2" : {
"name": "Jeremy",
"surname": "Smith",
"age": 42,
}
};
I want to convert this to
Map<String, dynamic> userMap = {
"id_1" : {
"id": "id_1",
"name": "John",
"surname": "Doe",
"age": 25,
},
"id_2" : {
"id": "id_2",
"name": "Jeremy",
"surname": "Smith",
"age": 42,
}
};
I tried this
userMap.entries.map((entry) => (entry.value as Map).putIfAbsent('id', () => entry.key));
but it is not working. Instead it is giving result as (id_1, id_2). What I am doing wrong ?? Is there any way to achieve the desired one ??
userMap.entries.map((entry) => (entry.value as Map).putIfAbsent('id', () => entry.key));
The reason why that doesn't work is because you don't do anything with the result of calling .map(). From the Iterable.map documentation:
Returns a new lazy Iterable.... As long as the returned Iterable is not iterated over, the supplied function f will not be invoked.
Your callback function thus is never called and will not mutate the original Map. You could forcibly iterate over the result of .map() (e.g. userMap.entries.map(...).toList()) to get your desired result. However that's wasteful and misuses Iterable.map.
Iterable.map is meant to be used to perform a functional transformation on an Iterable; you should not use it when the callback has side effects. (A "side effect" is something that the callback does other than just returning a value.) For callbacks where you care about side effects, either use Iterable.forEach or use a normal for loop.
You can use this:
userMap.forEach((k,v) => {(v as Map).putIfAbsent('id', () => k)});
Related
I am Beginner in flutter, learning map concept. I am confusing map methods. How to delete a specific value from a map?
for example:
Map data = {
"studet1": {"name": "ajk", "age": "22", "place": "delhi"},
"studet2": {"name": "akmal", "age": "25", "place": "up"}
};
I want to delete the "name" from "student1".
data is a nested map, which means that it has another map within the key of student1.
You can use the .remove method to remove a key within a map:
Removes key and its associated value, if present, from the map.
void main() {
Map data ={
"student1":{
"name" : "ajk",
"age":"22",
"place":"delhi"
},
"student2":{
"name" : "akmal",
"age":"25",
"place":"up"
}
};
data['student1'].remove('name');
print(data);
}
Prints:
{student1: {age: 22, place: delhi}, student2: {name: akmal, age: 25, place: up}}
If you want to remove only student1 name
Just use data['student1'].remove('name');
Or if you want to remove all students name use the bleow method
Map data = {
"studet1": {"name": "ajk", "age": "22", "place": "delhi"},
"studet2": {"name": "akmal", "age": "25", "place": "up"}
};
for (int i = 0; i <= data.length - 1; i++) {
data[data.keys.elementAt(i)].remove('name');
}
The output will be
{student1: {age: 22, place: delhi}, student2: {age: 25, place: up}}
Background
I have the following JSON data that is being remotely retrieved via an async request, that I'm trying to build a list view out of in Flutter.
As you can see the first item is 'logged in' which is totally different from all the other items
I'm having a lot of trouble in flutter when trying to build a list view out of the data (I'm a total flutter noob --> This is day 0).
[
{
"loggedin": "0"
},
{
"id": "1",
"title": "Title 1",
"excerpt": "",
"thumb": "Image 1.jpg",
"threadid": "1",
"fid": "1",
"commentcount": "1",
"postdate": 1
}, {
"id": "2",
"title": "Title 2",
"excerpt": "",
"thumb": "Image 2.jpg",
"threadid": "2",
"fid": "2",
"commentcount": "2",
"postdate": 2
}, {
"id": "3",
"title": "Title 3",
"excerpt": "",
"thumb": "Image3.jpg",
"threadid": "3",
"fid": "3",
"commentcount": "3",
"postdate": 3
}
]
My Conceptual Solution
I was thinking of stripping out the first item logged in and forming a whole new Json array with just Items 1-3
My Question
Is it possible to iterate through the decoded json data and form a new array?
I can successfully access an individual item in my list as follows:
_map = json.decode(response.body)[1];
However when I try to iterate through my list it fails
final decoded = json.decode(response.body) as dynamic;
decoded.forEach((key, value) {
if (key != "loggedin") {
debugPrint('hi');
}
});
If I try to iterate through just one of the items then it does work:
final decoded = json.decode(response.body)[1] as dynamic;
decoded.forEach((key, value) {
debugPrint(key+': '+value);
});
I needed to iterate through my list as a starting point to pick out the items I want to remove from my final list (basically the item with a key of "loggedin", but I'm failing miserably here
Alternatives
I realize the very concept of my approach is most likely flawed or tedious. If any other alternative approach to achieve my goal seems better I'm all ears! :)
The error's happening because your data is a list of maps but in the list iterator you are passing a function with two parameters, which works for a map.
You should do it like this -
final decoded = json.decode(response.body) as dynamic;
decoded.forEach((data) {
//data is a Map
});
You can access the individual keys like this - data["loggedin"]
To check whether it contains 'loggedin', you can do data.containsKey("loggedin")
For a list, the function in the forEach takes one Argument which is a list item, and for a Map it takes two, a key and its corresponding value.
I'd recommend creating a Model class with the below fields:
id
title
excerpt
thumb
threadid
fid
commentcount
postdate
loggedin
Now, for the first item, all fields will be null except loggedin and for other items loggedin will be null.
Convert response to List<Map>, iterate through list, ignore item that contains keys loggedin
final List<Map> list = json.decode(response.body);
list.forEach((element) {
if(!element.containsKey("loggedin")){
//Here element is map of your required item
//You can convert it to your required model
}
});
What is the best way to unmarshall this json in dart:
{
"Ace-spades-2": {
"rank": { "shortName": "A", "longName": "Ace" },
"suit": { "name": "spades" },
"id": "Ace-spades-2"
},
"Two-spades-2": {
"rank": { "shortName": "2", "longName": "Two" },
"suit": { "name": "spades" },
"id": "Two-spades-2"
},
"Three-spades-2": {
"rank": { "shortName": "3", "longName": "Three" },
"suit": { "name": "spades" },
"id": "Three-spades-2"
},
{....a bunch more cards}
}
Here are my classes that I want to unmarshall into. Specifically I want to make the data Map<String,Card>. How can I do this?
class Card {
Rank rank;
Suit suit;
String id;
Card({this.rank,this.suit,this.id})
}
class Rank {
String shortName;
String longName;
Rank({this.shortName, this.longName});
}
class Suit {
String name;
Suit({this.name});
}
In Go, I would just do
cards := map[string]Card{}
json.Unmarshal(<some_json>, &cards).
What is the best way to do this in dart?
For serialization in Flutter (where reflection is not available) is very common to use the json_serializable package. A good tutorial about this package is also in the flutter doc: https://flutter.dev/docs/development/data-and-backend/json#serializing-json-using-code-generation-libraries
When you have annotated yours classes (and you have completed the others installation instructions - also remember the annotation on the library declaration, which is mandatory), you can take advantage of the Card.fromJson() factory constructor. You can convert your json raw String in a Map<String, dynamic> using the jsonDecode() function (of the dart:convert package), then iterate on the Map and convert every entry in the Map with Card.fromJson.
For example:
Map<String, Card> cardMap = (jsonDecode(jsonString) as Map<String, dynamic>).map((key, cardString) => MapEntry(key, Card.fromJson(cardString)));
A very important note: when you have a class (Card and Rank, in your example) with fields whose type is not primitive, but instead represents another class annotated with JsonSerializable, the JsonSerializable annotation must pass explicitToJson: true (i.e. #JsonSerializable(explicitToJson: true) class Card).
The process to serialize class/deserialize json the first time isn't as fast as in Go, but flutter doesn't have reflection.
I have a JSON response from my API call. The format is like this.
[
{
"hotelname": "A",
"roomno": "101",
"occupancy": "4"
},
{
"hotelname": "A",
"roomno": "102",
"occupancy": "3"
},
{
"hotelname": "B",
"roomno": "101",
"occupancy": "4"
},
{
"hotelname": "B",
"roomno": "202",
"occupancy": "3"
}
]
I want to write a code where in one dropdown list displays the names of the hotels(A,B,C etc) the other dropdown should display the corresponding roomno.
To achieve this i would like to convert my JSON response to a MAP like the below.
Map<String,String> _hoteldata = {
"101":"A",
"102":"A",
"101":"B",
"202":"B",
};
First, you parse the json using jsonDecode(), then create a map from the list, for example, using Map.fromEntries():
import 'dart:convert';
var rooms = jsonDecode(json) as List;
var hotelData = Map.fromEntries(
rooms.map((room) => MapEntry(room['roomno'], room['hotelname']))
);
I need to convert every element of 'content' array to object.
Here is json:
{
"content": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"author": {
"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
},
"createDate": "2020-01-30T20:18:29.764Z",
"executor": {
"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
},
}
],
"first": true,
"numberOfElements": 0,
}
The problem is that 'content' array is inside json, and its parts as executor and author has to be objects too, and I don't know how to reach it and parse.
How it can be done? Any help, thanks.
You access the elements like this:
var decoded = json.decode(j);
var inner = decoded['content'][0]; // if you expect more than one entry, iterate the list
print(inner['id']); // -> 3fa85f64-5717-4562-b3fc-2c963f66afa6
print(inner['createDate']);
print(inner['author'].runtimeType); // another Map<String, dynamic> as expected
print(inner['author']['userId']);
You can create Dart classes to model, for example, a 'user' if you want.