Im trying to parse json into a list of Products using Dart 2 for web.
I have the following Class:
class Product {
final String Problem;
final String Owner;
final String Description;
const Product({
this.Problem,
this.Owner,
this.Description,
});
factory Product.parse(Map<String, dynamic> json) {
print(json);
return new Product(
Problem: json["Problem"],
Owner: json["Owner"],
Description: json["Description"]
);
}
}
And I am trying to parse this using:
Stream<Product> getProducts() async* {
final payload = await HttpRequest.getString("products.json");
print(payload);
//var _json = (json.decode(payload));
print("break");
var list = json.decode(payload);
print(list);
//print(list);
final productList = (json.decode(payload) as List).cast<Map<String, dynamic>>();
}
However this fails with this error:
EXCEPTION: Type '_JsonMap' is not a subtype of expected type
'List'.
I can see that I have a list[Symbol(_original)] when I debug, but when I try to evaluate this, I returns as undefined.
I also tried
List list = json.decode(payload) as List;
List<dynamic> list = json.decode(payload);
List<dynamic> list = json.decode(payload) as List<dynamic>;
var list = (json.decode(payload)).cast<Map<String, dynamic>>();
var list = (json.decode(payload)).cast<Map<dynamic, dynamic>>();
but get the same error.
Json
{
"Product_One": {
"Owner": "test",
"Description": "test description",
"Theme_Objective": "test objective",
"Technical_details": "test technical details",
"Problem": "test",
"Solution": "test"
}
}
Your JSON does not contain any list, it's all maps.
When you try to cast a Map to List, it has to fail since maps are not lists.
Maybe you want to do:
final productList = (jsonDecode(payload) as Map).values.toList();
This gives you a list of the product maps, without the names that you don't appear to be using anyway.
Related
I am trying to convert this dart file here to use generics and I get the following error when trying to initialize an empty list in constructor.
Constant list literals can't include a type parameter as a type
argument, such as 'T'. Try replacing the type parameter with a
different
How can I create an empty list in this case. Below code can elaboreate my problem even more
old file
enum PostStatus { initial, success, failure }
class PostState extends Equatable {
const PostState({
this.status = PostStatus.initial,
this.posts = const <Post>[],
this.hasReachedMax = false,
});
final PostStatus status;
final List<Post> posts;
final bool hasReachedMax;
PostState copyWith({
PostStatus status,
List<Post> posts,
bool hasReachedMax,
}) {
return PostState(
status: status ?? this.status,
posts: posts ?? this.posts,
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
);
}
#override
List<Object> get props => [status, posts, hasReachedMax];
}
new file
class PagedState<T> extends Equatable {
const PagedState({
this.status = PagedStatus.initial,
this.items = const <T>[], //ERROR HERE
this.hasReachedMax = false,
});
final PagedStatus status;
final List<T> items;
final bool hasReachedMax;
PagedState copyWith({
PagedStatus status,
List<T> items,
bool hasReachedMax,
}) {
return PagedState(
status: status ?? this.status,
items: items ?? this.items,
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
);
}
#override
List<Object> get props => [status, items, hasReachedMax];
}
As the error says, constant list literals can't use a type parameter, so you must use a non-const literal: <T>[].
However, since it's a default argument and default arguments must be constants, that won't work either. You either will need to:
Use a constant sentinel value as the default and replace it with the desired default later:
const PagedState({
List<T> items = null,
this.hasReachedMax = false,
}) : items = items ?? <T>[];
Use const [] without the explicit type parameter and let automatic type conversions do the work for you.
I will like to store a list of values from an API locally. Does shared preference allow storing List because each time i try to save my values in shared preference, i get " type 'List' is not a subtype of type 'List'"
Future fetchAllProduct() async{
try{
for(int j = 1; j < 3; j++){
final response = await
http.get('https://website/api/?page=1',
);
List result = json.decode(response.body);
products.addAll(result);
//Saving fetched product list
SharedPreferences preferences = await SharedPreferences.getInstance();
preferences.setStringList('prds', products);
//final prds = preferences.getStringList('prd');
}
}catch (ex){
print('$ex');
}
print(products);
}
I'am expecting to see a list like this
[{ProductID: 155, Name: Multi-vit, Description: Multi-vit, CostPrice: 0.0, SalePrice: 80, EatOutPrice: 80, CategoryID: 976, Barcode: , TaxRateID: null, }]
According to shared_preference's repo it should be possible to store a List. Their test case have a slightly different syntax than yours:
preferences.setStringList('List', kTestValues2['flutter.List']) which is different from your approach.
I assume you have defined products as a List.
EDIT:
Why are you storing a list inside a list? What happens if you make your result a String?
An easy way would be to encode the List as a JSON and save that as a string.
import 'dart:convert' show json;
import 'package:shared_preferences/shared_preferences.dart';
void setList(String key, List<dynamic> value) async {
await setString(key, json.encode(value));
}
setList('key', []);
all my JSON data contains status(int), msg(String), and data(any Type). Because I'm come from java ,I want use generics。I'm writing a deserialize for a top generics with built_value, but failed.
I have try this
https://github.com/google/built_value.dart/blob/master/end_to_end_test/test/generics_serializer_test.dart.
But do not really understand.
There follows my code:
abstract class GenericValue<T>
implements Built<GenericValue<T>, GenericValueBuilder<T>> {
T get data;
int get status;
String get msg;
GenericValue._();
static Serializer<GenericValue> get serializer => _$genericValueSerializer;
factory GenericValue([updates(GenericValueBuilder<T> b)]) =
_$GenericValue<T>;
}
abstract class UserInfo implements Built<UserInfo, UserInfoBuilder> {
static Serializer<UserInfo> get serializer => _$userInfoSerializer;
String get id;
String get email;
UserInfo._();
factory UserInfo([updates(UserInfoBuilder b)]) = _$UserInfo;
}
GenericValue<UserInfo> parseUserInfo(String jsonStr) {
final parsed = json.jsonDecode(jsonStr);
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFac`enter code here`tory(specifiedType, () => GenericValueBuilder<UserInfo>
()))
.build();
Response<UserInfo> response = serializersWithBuilder.deserialize(parsed,
specifiedType: specifiedType);
return response;
}
but result is: Invalid argument(s): Unknown type on deserialization. Need either specifiedType or discriminator field.
how can it do it in right way, to deserialize JSON data like this.
String toJsonUserInfo() {
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFactory(
specifiedType, () => GenericValueBuilder<UserInfo>()))
.build();
return json.encode(
serializersWithBuilder.serialize(this, specifiedType: specifiedType));
}
static GenericValue<UserInfo> fromJsonUserInfo(String jsonString) {
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFactory(
specifiedType, () => GenericValueBuilder<UserInfo>()))
.build();
return serializersWithBuilder.deserialize(json.decode(jsonString),
specifiedType: specifiedType);
}
it works.
I have list from a model like this
amount:"12000"
dateTime:"19/07/2018"
detail:"Soto"
hashCode:853818549
id:1
name:"Theodorus"
I want to just select amount and add it to another list of string, but I'm always getting this error A value of type 'String' can't be assigned to a variable of type 'List<String>'. , I thinks its because im not doing it right, here is my code below
void setupList() async {
DebtDatabase db = DebtDatabase();
listCache = await db.getMyDebt();
setState(() {
filtered = listCache;
});
List<String> amount = new List<String>();
listCache.map((value) {
amount = value.amount; } );
//print(amount);
}
can anyone help me, so I can get list of ammount from this model list and then sum all the ammount?
The map function returns an iterable and you can then transform it into a list.
You should try something like this:
void setupList() async {
DebtDatabase db = DebtDatabase();
listCache = await db.getMyDebt();
setState(() {
filtered = listCache;
});
List<String> amount = listCache.map((value) => value.amount).toList();
//print(amount);
}
How would I do the Dart equivalent of this Java code?
Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> cons = c.getConstructor(String.class);
Object object = cons.newInstance("MyAttributeValue");
(From Jeff Gardner)
The Dart code:
ClassMirror c = reflectClass(MyClass);
InstanceMirror im = c.newInstance(const Symbol(''), ['MyAttributeValue']);
var o = im.reflectee;
Learn more from this doc: http://www.dartlang.org/articles/reflection-with-mirrors/
(From Gilad Bracha)
Using built_mirrors you can do it next way:
library my_lib;
import 'package:built_mirrors/built_mirrors.dart';
part 'my_lib.g.dart';
#reflectable
class MyClass {
String myAttribute;
MyClass(this.myAttribute);
}
main() {
_initMirrors();
ClassMirror cm = reflectType(MyClass);
var o = cm.constructors[''](['MyAttributeValue']);
print("o.myAttribute: ${o.myattribute}");
}
This was an issue that has plagued me until I figured that I could implement a crude from method to handle the conversion of encoded Json Objects/strings or Dart Maps to the desired class.
Below is a simple example that also handles nulls and accepts JSON (as the string parameter)
import 'dart:convert';
class PaymentDetail
{
String AccountNumber;
double Amount;
int ChargeTypeID;
String CustomerNames;
PaymentDetail({
this.AccountNumber,
this.Amount,
this.ChargeTypeID,
this.CustomerNames
});
PaymentDetail from ({ string : String, object : Map }) {
var map = (object==null) ? (string==null) ? Map() : json.decode(string) : (object==null) ? Map() : object;
return new PaymentDetail(
AccountNumber : map["AccountNumber"] as String,
Amount : map["Amount"] as double,
ChargeTypeID : map["ChargeTypeID"] as int,
CustomerNames : map["CustomerNames"] as String
);
}
}
Below is it's implementation
PaymentDetail payDetail = new PaymentDetail().from(object: new Map());
PaymentDetail otherPayDetail = new PaymentDetail().from(object: {"AccountNumber": "1234", "Amount": 567.2980908});
Once again, this is simplistic and tedious to clone throughout the project but it works for simple cases.