Im setting up firebase cloud messaging and in my onResume() callback I have the following:
Future<void> onResume(Map<String, dynamic> message) async {
final Map<String,dynamic> data = message['data'];
final String url = data['url'];
if (url != null) {
_webViewController?.loadUrl(url);
}
}
When the function reaches
final Map<String,dynamic> data = message['data'];
it returns prematurely and silently without warnings.
If I instead run
final dynamic data = message['data'];
it continues as expected.
Inspecting the message type revels that message is InternalLinkedHashMap and cannot be cast too Map<String, dynamic>.
It says _InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>'.
How do I do this?
How can I find this issue in the future if it has no trace?
I found the best way to solve it were to use Map.from() and specify the variable type as Map:
final Map<String, dynamic> data = Map.from(message['data']);
Try this:
final Map<String,dynamic> data = Map.castFrom<dynamic, dynamic, String, dynamic>(message['data']);
You should only do this, of course, if all of your keys are really Strings.
If you want to understand what's going on, see this:
var x = {};
print(x.runtimeType);
Map<String, dynamic> y = Map.castFrom<dynamic, dynamic, String, dynamic>(x);
print(y.runtimeType);
You can try to map all keys to string. Something like:
final Map<String,dynamic> data = message.map((key, value) => MapEntry(key.toString(), value));
Related
I am trying to fill up a Map from DocumentSnapshot in a Flutter.
but I'm having a syntax error within the code.
This is the code I'm trying to work with:
Future<Map<String, dynamic>> particularItem(String productId) async {
DocumentSnapshot prodRef = await _productReference.doc(productId).get();
Map<String, dynamic> itemDetail = new Map();
itemDetail['image'] = await getProductsImage(prodRef.data()['imageId'][0]);
itemDetail['color'] = prodRef.data()['color'];
itemDetail['size'] = prodRef.data()['size'];
itemDetail['price'] = prodRef.data()['price'];
itemDetail['name'] = prodRef.data()['name'];
itemDetail['productId'] = productId;
return itemDetail;
}
And this is the error I'm getting in the below snippet:
The operator '[]' isn't defined for the type 'Object'. Try defining the operator '[]'.
prodRef.data()['imageId']
prodRef.data()['color']
prodRef.data()['size']
prodRef.data()['price']
prodRef.data()['name']
You should cast prodRef.data() before use it. In dart object can't not use the operator []
final data = prodRef.data() as Map<String, dynamic>;
Then you can get property from data variable.
For more, you can read here Firebase documentation
I am trying to get the JSON response from the server and output it to the console.
Future<String> login() async {
var response = await http.get(
Uri.encodeFull("https://etrans.herokuapp.com/test/2"),
headers: {"Accept": "application/json"});
this.setState(() {
data = json.decode(response.body);
});
print(data[0].name);
return "Success!";
}
Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is
not a subtype of type 'List
What could be the reason?
Here are 2 common ways this could go wrong:
If your response is a json array like
[
{
key1: value1,
key2: value2,
key3: value3,
},
{
key1: value1,
key2: value2,
key3: value3,
},
.....
]
Then, we use data[0]["name"], not data[0].name
Unless we cast to an object that has the name property, we cannot use data[0].name
We cast like this data = json.decode(response.body).cast<ObjectName>();
ObjectName can be whatever object you want (Inbuilt or Custom). But make sure it has the name property
If your response is a JSON object like
{
dataKey: [
{
key1: value1,
key2: value2,
key3: value3,
}
]
}
Then json.decode will return a Map, not a List
Map<String, dynamic> map = json.decode(response.body);
List<dynamic> data = map["dataKey"];
print(data[0]["name"]);
You can use
new Map<String, dynamic>.from(snapshot.value);
Easiest way (one dimensional):
Map<String, dynamic> data = new Map<String, dynamic>.from(json.decode(response.body));
print(data['name']);
You are trying to case an Instance of InternalLinkedHashMap which is not possible.
You should Serialize and deserialize it back to Map<String, dynamic>.
InternalLinkedHashMap<String, dynamic> invalidMap;
final validMap =
json.decode(json.encode(invalidMap)) as Map<String, dynamic>;
You have to convert the runtimeType of data from _InternalLinkedHashMap to an actual List.
One way is to use the List.from.
final _data = List<dynamic>.from(
data.map<dynamic>(
(dynamic item) => item,
),
);
If you need work with generic fields has a workaround:
class DicData
{
int tot;
List<Map<String, dynamic>> fields;
DicData({
this.tot,
this.fields
});
factory DicData.fromJson(Map<String, dynamic> parsedJson) {
return DicData(
tot: parsedJson['tot'],
//The magic....
fields : parsedJson["fields"] = (parsedJson['fields'] as List)
?.map((e) => e == null ? null : Map<String, dynamic>.from(e))
?.toList()
);
}
}
You can get this error if you are using retrofit.dart and declare the wrong return type for your annotated methods:
#GET("/search")
Future<List<SearchResults>> getResults();
// wrong! search results contains a List but the actual type returned by that endpoint is SearchResults
vs
#GET("/search")
Future<SearchResults> getResults();
// correct for this endpoint - SearchResults is a composite with field for the list of the actual results
This worked for me:
Create a List Data
Use Map to decode the JSON file
Use the List object Data to fetch the name of the JSON files
With the help of index and the list object I have printed the items dynamically from the JSON file
setState(){
Map<String, dynamic> map = json.decode(response.body);
Data = map["name"];
}
// for printing
Data[index]['name1'].toString(),
Seems like this error could pop up depending on various developer faults.
In my case, I was using an EasyLocalization key but without defining it under asset/lang/en_US.json file.
If your working with Firebase Cloud,make sure that you're not trying to add multiple data with same DocumentID;
firestore.collection('user').document(UNIQUEID).setData(educandos[0].toJson()).
To convert from _InternalLinkedHashMap<String, dynamic> to Map<String, double> I used
Map<String,double>.from(json['rates'])
I had the same error using json_annotation, json_serializable, build_runner. It occurs when calling the ClassName.fromJson() method for a class that had a class property (example: class User has a property class Address).
As a solution, I modified the generated *.g.dart files of each class, by changing Map<String, dynamic>) to Map<dynamic, dynamic>) in everywhere there is a deep conversion inside the method _$*FromJson
The only problem is that you have to change it again every time you regenerate your files.
In firestore, I have an array of (simple) maps.
When getting this data into Flutter/Dart, using the cloud_firestore package as follows:
Stream<T> documentStream<T>({
required String path,
required T Function(Map<String, dynamic>? data, String documentID) builder})
{
final DocumentReference<Map<String, dynamic>> reference =
FirebaseFirestore.instance.doc(path);
final Stream<DocumentSnapshot<Map<String, dynamic>>> snapshots =
reference.snapshots();
return snapshots.map((snapshot) => builder(snapshot.data(), snapshot.id));
}
and consuming this e.g. as follows:
documentStream(
path: 'firestore_path_doc',
builder: (data, documentId) {
final x = data['array_of_maps'];
print(x[0].runtimeType); // gives LinkedMap<String, dynamic>
final y = x as List<Map<String, String>>; // fails
final y1 = x[0] as Map<String, String>; // fails
},
);
fails.
I cannot find a way to convert the map inside this array to a normal map.
In fact, I can barely find any info on LinkedMap. After digging, I see its in the js (https://pub.dev/packages/js) package, but it's internal there, not supposed to be exposed.
If I had a map in firestore, it converts easily to a Map<String, String> in dart. But a map inside an array arrives as a LinkedMap.
How can I work this LinkedMap? I cannot even iterate over it, since it is not recognised at compile time, even if I try to import js.
thx
I got it to work following the answer to this: How to convert an array of map in Firestore to a List of map Dart
Basically by using a class for the inner map instead of a generic Map.
x[0] type is Map<String, dynamic>. You're trying to cast it to Map<String, String>, which would obviously fail.
You can do that manually though:
final x = data['array_of_maps'] as List<Map<String, dynamic>>;
final myMap = x[0].map((key, value) => MapEntry(key, value.toString()));
The error is when I try to use the ModalRoute.of(context).settings.arguments I get an error. Also I want to save it in a map but can't.
Map data = {};
data = ModalRoute.of(context).settings.arguments; // this is the error;
Error: A value of type 'Object?' can't be assigned to a variable of type 'Map<dynamic, dynamic>'.
'Object' is from 'dart:core'.
'Map' is from 'dart:core'.
data = ModalRoute.of(context).settings.arguments;
After passing so many problems, finally, the solution is surprisingly easy.
Map data = {};
data = ModalRoute.of(context).settings.arguments as Map;
Try using:
data=ModalRoute.of(context)?.settings?.arguments as Map;
The ? is used for null safety
You can do that with the below code:
Map <String, Object>data = {}; // as the arguments passed from
data = {"dataKey":ModalRoute.of(context).settings.arguments};
And later, access your arguments by calling
data["dataKey"] // it will return the arguments
I was facing a similar issue and I think this solution will help you
Map data = ModalRoute.of(context)!.settings.arguments as Map;
Put the below code inside of your StatefulWidget class
Map userdata = {};
userdata = ModalRoute.of(context)!.settings.arguments as Map;
print(userdata);
Your output looks like something this
flutter: {firstName: Dhaval, lastname: Gevariya}
after lot of searching this coda works
Map data = {};
data = ModalRoute.of(context)?.settings.arguments as Map;
Define the argument Like :
class ProductDetailsArguments {
final Product product;
ProductDetailsArguments({required this.product});
}
extracts the arguments Like
final args = ModalRoute.of(context)!.settings.arguments as ProductDetailsArguments;
To solve the issue, I did :
Map <String, dynamic> data = {};
data = ModalRoute.of(context).settings.arguments as Map<String, dynamic>;
I am new to flutter, so I honestly don't know the why I am receiving this error.
List < BaseResponse > pEShippingDetail = [];
Future loadMessageList() async {
http.Response response = await http.get('xxxxx');
//await Future.delayed(Duration(seconds: 3));
String content = response.body;
List collection = json.decode(content);
List < BaseResponse > _messages = collection.map((json) => BaseResponse.fromJson(json)).toList();
setState(() {
pEShippingDetail = _messages;
});
}
void initState() {
loadMessageList();
super.initState();
}
Your json.decode(content); produced a _InternalLinkedHashMap<String, dynamic> but you are try to assign it to a List of type dynamic(default type).
To solve this, first see what is the data format of the response is. Then use required type. You could use final without static type but that's not the best option here. Map<String, dynamic> should work but cannot explicitly say it is correct without looking at the json response.
That get request is returning a JSON object, not a list. JSON objects are decoded to Map<String, dynamic>. So the exception is because you are trying to assign a Map<String, dynamic> to a List variable, which cannot be done.
Looking at the response above though, perhaps you mean to use the categories property in the response, not the entire response?
Have a closer look at the response, and decide which parts of the data you are actually interested in.