Flutter: InternalLinkedHashMap<String, dynamic>' has no instance method 'cast' with matching arguments - android

I'm unable to find solutions from the previously available question, I have cast json string to map
Below is my API calling method.
Future<EventResponse> fetchEvent( ) async { // here i change Future type
String url='http://xxxxxxxxxxxx.tk/api/userapp/event/lists';
var headers = new Map<String, String>();//here i defined Map type
headers['Auth-Key'] = 'OCDOC#2018';
headers['End-Client'] = 'OCDOC';
var body = new Map<String, String>();//here i defined Map type
headers['schedule'] = 'present';
http.Response res = await http.post(url,headers: headers, body: body);
final parsed=json.decode(res.body);
var myMap = Map<String, dynamic>.from(parsed);
EventResponse eventResponse = EventResponse.convertEventResponse(myMap);
return eventResponse;
}
this is my convertEventResponse methode
factory EventResponse.convertEventResponse(Map<String, dynamic> json) {
List<dynamic> events = json['eventList'];
List<Event> eventList = events.map((e) => Event.convertEvent(e)).toList(); //here i changed by #Richard Heap answer
return EventResponse(
error: json['error'],
status: json['status'],
deliveryCharges: json['deliveryCharge'],
imageBaseUrl: json['image_base_url'],
imageLogoUrl: json['image_logo_url'],
eventList: eventList,
);
}
The error i'm getting.
InternalLinkedHashMap<String, dynamic>' has no instance method 'cast' with matching arguments.

Use instead
.cast<String,dynamic>();
See also https://api.dartlang.org/stable/2.0.0/dart-core/Map/cast.html
Usually it's better to use Map<String,String>.from(oldMap) instead of cast<...>(...)

Related

This expression has a type of 'void' so its value can't be used on Map

I'm new in flutter.
I'm receiving data from a DB server.
Map<String, double> dataMap = {};
var queryService = client.getQueryService();
var records = await queryService.query(query);
await records.forEach((record) {
DateFormat dateFormat = DateFormat("HH:mm:ss");
String formatedDate = dateFormat.format(DateTime.parse('${record['_time']}')); //Converting DateTime object to String
dataList.add('$formatedDate : ${record['_value']}');
dataMap[formatedDate] = double.parse('${record['_value']}');
});
print(dataMap);
client.close();
So I need to pass the dataMap data to a function:
dataMap.forEach((key, value) {
ChartData (key, value);
})
But I'm receiving the 'void' error... Any ideas?
Iterable.forEach does not return anything. It makes no sense to await its result. Map.forEach similarly does not return anything, so you cannot pass its result as an argument to a function. Additionally, your callback does not do anything; ChartData(key, value) by itself constructs a ChartData object but then discards it.
If you want to convert dataMap to a List<ChartData>, you need to iterate over dataMap and build a List:
var chartDataList = dataMap.entries.map(
(keyValue) => ChartData(keyValue.key, keyValue.value),
).toList();
or use collection-for:
var chartDataList = [
for (var keyValue in dataMap.entries)
ChartData(keyValue.key, keyValue.value),
];

Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'OriginDestination' in type cast int flutter

I am trying to fetch data from a local json file in my assets. I received and decoded data and then tried to store it in a list for further use. But it give me the exception. I want the list to be of type OriginDestination, store it in database and then use it further. Can someone please tell me how can I parse data from json to OriginDestination.
Class OriginDestination -
OriginDestination cityDtoFromJson(String str) => OriginDestination.fromJson(json.decode(str));
String cityDtoToJson(OriginDestination data) => json.encode(data.toJson());
#HiveType(typeId: 0)
// ignore: non_constant_identifier_names
class OriginDestination extends HiveObject {
#HiveField(0)
City? origin;
#HiveField(1)
List<City>? destinations;
OriginDestination({
this.origin,
this.destinations,
});
factory OriginDestination.fromJson(Map<String, dynamic> json) => OriginDestination(
origin: City.fromJson(json["origin"]),
destinations: List<City>.from(
json["destinations"].map((x) => City.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"origin": origin,
"destinations": destinations,
};
Code where I am fetching data and want to use it (originDestinations is also a list of type OriginDestination) -
List<OriginDestination>? localOriginDestination = [];
Future<void> readJson() async {
final String response = await rootBundle.loadString('assets/files/node.json');
final data = await json.decode(response);
localOriginDestination = await data["data"].cast<OriginDestination>();
print(localOriginDestination);
if(localOriginDestination!=null) {
await _localStorageService.getBox().clear();
await _localStorageService.getBox().addAll(localOriginDestination!.toList());
originDestinations = _localStorageService.getOriginDestinations();
}
}
I have never used Hive before but this line of code seems suspicious to me:
localOriginDestination = await data["data"].cast<OriginDestination>();
I think you want to do something along the lines of:
localOriginDestination = [
for (final element in await data['data']) OriginDestination.fromJson(element),
];
But I can't be entirely certain without knowing what the value of await data['data'] is.
Edit, adding some more information.
The .cast method on List is only meant to be used with a type that is a subtype of the original list type, like in this example:
void main() {
List<num> nums = [1, 2, 3];
List<int> ints = nums.cast<int>();
ints.add(4);
print(ints);
}
What you are doing is essentially the same thing as this.
void main() {
List<Map<String, int>> items = [
{'A': 1, 'B': 2},
{'A': 3, 'B': 4},
];
final result = items.cast<ABC>();
print(result);
}
class ABC {
int a;
int b;
ABC.fromJson(Map<String, dynamic> json)
: a = json['A'],
b = json['B'];
}
The problem here is that the ABC class is not a subtype of Map<String, int>. Classes are not maps in the dart programming language. You need to need to call the .fromJson constructor on each element of the items list in order to get a List<ABC>.
You can do it in a few different ways.
Using map method is one approach. (you need to be on dart 2.15+ for this exact syntax)
List<ABC> result = items.map(ABC.fromJson).toList();
Looping over items with a collection for is another approach.
List<ABC> result = [for (final element in items) ABC.fromJson(element)];
Looping over items with a conventional for loop is yet another approach.
List<ABC> result = [];
for (final element in items) {
result.add(ABC.fromJson(element));
}

"The getter 'body' isn't defined for the type 'Response<dynamic>". on Flutter

i'm having a problem to put a response json on a List.
When i try to transform the body data (where the data comes) i get the error:
The getter 'body' isn't defined for the type 'Response<dynamic>'.
Try importing the library that defines 'body', correcting the name to the name of an existing getter, or defining a getter or field named 'body'.dartundefined_getter
My code is:
onPressed: () async {
Response response;
Dio dio = new Dio();
String url =
'http://192.168.15.5:8090/api/getOs';
response = await dio.post(url, data: {
"numeroos": _numeroOsController.text
});
final extractedData = json.decode(response.body) //Here is the error
as Map<String, dynamic>;
final List<ProdutoOs> loadedProducts = [];
extractedData.forEach((key, value) {
loadedProducts.add(ProdutoOs(
cod_produto: value['Codigo_Produto'],
qtd: value['Qtde'],
desc: value['Descricao'],
numOs: value['Numero_da_OS'],
codOs: value['CodOS']));
Navigator.pop(context, true);
});
}
So i'm trying to put the response.body in a List but i cant, what am i doing wrong?
I have also tried using response.data and dont get the same error, the app runs but i get:
E/flutter (11379): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'String'
Maybe try this:
List responseElements = jsonDecode(response.body);
responseElements.map((singleJsonObject) => {
// do your parsing here
});
Add the await keyword when you're parsing the url
add await before parsing the url

Flutter: How to JSON encode a `List` properly?

I am trying to pass a List to my server using flutter, via a REST API.
Below is the code
Future<void> saveOrderItemList(List<OrderItem> orderItems) async {
int responsetag = 0;
try {
await http.post("http://url to post the data",
body: convert.json.encode(orderItems.toJson()), //This line do not work
headers: {
"Accept": "application/json",
"content-type": "application/json"
}).then((http.Response response) {
final int statusCode = response.statusCode;
print("RESPONSE: " + response.body);
print("STATUS CODE: " + statusCode.toString());
if (statusCode < 200 || statusCode > 400 || response.body == null) {
throw new Exception("Error while fetching data");
} else {
responsetag = int.parse(response.body);
}
});
return responsetag;
} catch (error) {
throw (error);
}
}
The above code doesn't run because I can't encode a List using convert.json.encode(orderItems.toJson()).
Below is my code for OrderItem bean and its serialisation class.
part 'order_item.g.dart';
/// An annotation for the code generator to know that this class needs the
/// JSON serialization logic to be generated.
#JsonSerializable()
class OrderItem {
int idorderItem;
FreshProducts freshProducts;
Order order;
ProductSize productSize;
double orderItemExpectedPricePerKg;
double orderItemQuantity;
int dateCreated;
int lastUpdated;
OrderItem(
{
this.idorderItem,
this.freshProducts,
this.order,
this.productSize,
this.orderItemExpectedPricePerKg,
this.orderItemQuantity,
this.dateCreated,
this.lastUpdated
});
/// A necessary factory constructor for creating a new User instance
/// from a map. Pass the map to the generated `_$OrderItemFromJson()` constructor.
/// The constructor is named after the source class, in this case User.
factory OrderItem.fromJson(Map<String, dynamic> json) => _$OrderItemFromJson(json);
/// `toJson` is the convention for a class to declare support for serialization
/// to JSON. The implementation simply calls the private, generated
/// helper method `_$OrderItemToJson`.
Map<String, dynamic> toJson() => _$OrderItemToJson(this);
}
And
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'order_item.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
OrderItem _$OrderItemFromJson(Map<String, dynamic> json) {
return OrderItem(
idorderItem: json['idorderItem'] as int,
freshProducts: json['freshProducts'] == null
? null
: FreshProducts.fromJson(json['freshProducts'] as Map<String, dynamic>),
order: json['order'] == null
? null
: Order.fromJson(json['order'] as Map<String, dynamic>),
productSize: json['productSize'] == null
? null
: ProductSize.fromJson(json['productSize'] as Map<String, dynamic>),
orderItemExpectedPricePerKg:
(json['orderItemExpectedPricePerKg'] as num)?.toDouble(),
orderItemQuantity: (json['orderItemQuantity'] as num)?.toDouble(),
dateCreated: json['dateCreated'] as int,
lastUpdated: json['lastUpdated'] as int,
);
}
Map<String, dynamic> _$OrderItemToJson(OrderItem instance) => <String, dynamic>{
'idorderItem': instance.idorderItem,
'freshProducts': instance.freshProducts,
'order': instance.order,
'productSize': instance.productSize,
'orderItemExpectedPricePerKg': instance.orderItemExpectedPricePerKg,
'orderItemQuantity': instance.orderItemQuantity,
'dateCreated': instance.dateCreated,
'lastUpdated': instance.lastUpdated,
};
how can I make sure I Can pass a list to POST from flutter http?
I solved a similar type of problem. But my List was wrap with a other keys like {"data":listOfItemJson} . So I first created a Map like that var map = {"data": MainOrderController.orderModel.toJson()}; and when i post this the uril i updated post mechanism like :
var response =
await http.post(url, headers: headers, body: jsonEncode(map));
Note: jsonEncode() is part of import 'dart:convert'; package.
I hope you can get an Idea
My take on this would be to replace json_serializable library with https://github.com/k-paxian/dart-json-mapper
It's quite similar, but don't over-bloats your code with boilerplate and not forcing you to maintain loads of '*.g.part' files, etc.
It will help you not only for this case, but for all Dart Object => JSON => Dart Object cases.
Please carefully read library readme document first, especially section "Basic setup".
With dart-json-mapper your code could look like this:
import 'main.reflectable.dart' show initializeReflectable;
import 'package:dart_json_mapper/dart_json_mapper.dart' show jsonSerializable, JsonMapper;
#jsonSerializable
#Json(enumValues: ProductSize.values)
enum ProductSize {Big, Small}
#jsonSerializable
class Order {
// ...
}
#jsonSerializable
class FreshProducts {
// ...
}
#jsonSerializable
class OrderItem {
int idorderItem;
FreshProducts freshProducts;
Order order;
ProductSize productSize;
double orderItemExpectedPricePerKg;
double orderItemQuantity;
int dateCreated;
int lastUpdated;
OrderItem(
{
this.idorderItem,
this.freshProducts,
this.order,
this.productSize,
this.orderItemExpectedPricePerKg,
this.orderItemQuantity,
this.dateCreated,
this.lastUpdated
});
}
void main {
initializeReflectable();
final orderItems = <OrderItem>[OrderItem(), OrderItem(), OrderItem()];
// Instead of convert.json.encode(orderItems.toJson())
final orderItemsJson = JsonMapper.serialize(orderItems);
// orderItemsJson will have Json string which you could pass as body to your post request
}
According json_serializable and https://github.com/google/json_serializable.dart/issues/651 ,you can put the following to build.yaml in root folder. The explicit_to_json default is false, set it true and it will explicitly call the nested toJson.
targets:
$default:
builders:
json_serializable:
options:
# Options configure how source code is generated for every
# `#JsonSerializable`-annotated class in the package.
#
# The default value for each is listed.
explicit_to_json: true

Flutter - unable to parse json array

I want to fetch list of cities from rest webservice, this way:
Future<List<City>> fetchCities() async {
final response =
await http.get('https://my-url/city',
headers: {HttpHeaders.acceptHeader: "application/json"});
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
return compute(parseCities, response.body);
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load cities');
}
}
Then to parse:
List<City> parseCities(String responseBody) {
final parsed = json.decode(responseBody)['data']['children'].cast<Map<String, dynamic>>();
return parsed.map<City>((json) => City.fromJson(json['data'])).toList();
}
And this is City class definition:
class City {
final String id;
final String name;
City({this.id, this.name});
factory City.fromJson(Map<String, dynamic> json) {
return City(
id: json['id'],
name: json['name'],
);
}
}
My example responseBody is:
[{\"id\":\"599\",\"name\":\"Bia\u0142ystok-dev\",\"location\":{\"long\":\"23.15\",\"lat\":\"53.13\"}}]
(for now, I want to ommit location and only fetch id and name). My json.decode throws exception:
type 'String' is not a subtype of type 'int' of 'index'
How to fix that? Any ideas?
The json string you have posted does not contain the keys data or children so to parse that json you would need to change your parse method to the following:
List<City> parseCities(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<City>((json) => City.fromJson(json)).toList();
}
although I think its good practice to use List.from instead of .cast
final parsed = List<Map<String, dynamic>>.from(json.decode(responseBody));

Categories

Resources