I've been trying to figure out how to use a named constructor to construct super and sub classes from JSON. Below is my example with some notes on what I've tried in the fromJson method body. Can anyone point me in the right direction? Thanks!
class Item {
final String name;
final int id;
final String image;
final double price;
final bool available;
Item(this.name, this.id, this.image, this.price, this.available);
Item.fromJson(Map<String, dynamic> json)
: name = json['name'],
id = json['id'],
image = json['image'],
price = json['price'],
available = json['available'];
}
class CartItem extends Item {
final int quantity;
CartItem({
#required this.quantity,
#required name,
#required id,
#required price,
#required image,
#required available
}): super(id, name, image, price, available)
CartItem.fromJson(Map<String, dynamic> json)
: quantity = json['quantity'],
// for whatever ever reason, super here seems to refer to CartItem
// so this doesn't work
super.name = json['name'],
// calling 'name' without the super doesn't work either
name = json['name']
}
You should use a the super's fromJson constructor in the child class's fromJson constructor. You can pass the Map in the child directly to the super without issues. Ex:
CartItem.fromJson(Map<String, dynamic> json)
: quantity = json['quantity'],
super.fromJson(json);
Related
I have code like this
class Human<T> { // <--- this is the superclass
final String name;
final T belongings;
Human({
required this.name,
required this.belongings,
});
}
class Athlete<T> extends Human { // <--- this is the subclass
final String sportType;
Athlete({
required String name,
required belongings,
required this.sportType,
}) : super(name: name, belongings: belongings);
}
final messi = Athlete<List<String>>( // <--- past List<String> as generic
name: "Lionel Messi",
belongings: ["Jersey", "Shoes"],
sportType: "Football",
);
final belonging = messi.belongings; // <-- the data type is dynamic, not List<String>
as you can see, I want belongings property to be generic, but after I pass List<String> as a generic type when instantiating an Athlete model, I still get dynamic data type like the image below, I expect it will be List<String> .
You need to add the <T> to Human, so it's extends Human<T>.
You also need to type the required belongings, parameter, either as
required T belongings,, or by using the new super-parameters feature and make it required super.belongings.
That is:
class Human<T> {
final String name;
final T belongings;
Human({
required this.name,
required this.belongings,
});
}
class Athlete<T> extends Human<T> { // <--- added <T>
final String sportType;
Athlete({
required super.name, // <--- used super.name
required super.belongings, // <--- used super.longings
required this.sportType,
}); // <--- no constructor call needed when it's all "super." parameters.
}
final messi = Athlete<List<String>>(
name: "Lionel Messi",
belongings: ["Jersey", "Shoes"],
sportType: "Football",
);
you have to declare belongings as a List within the human class like this:
final List<String> belongings;
Human({required this.belongings})
I am new in Dart(OOP Languange) which it is a bit similar in Java
But this code get me confusion
What is the purpose of colon(:) before the super keyword within SchoolID class that has been inherit with Person class?
Here is the code:
class Person {
String name;
int age;
int height;
Person({this.name, this.age, this.height});
}
class SchoolID extends Person {
int id;
int year;
String name;
SchoolID({this.id, this.year, this.name}) : super(name: name);
}
Another Example ,,, focus on colon the fishmap
AllFish.fromJson(Map<String, dynamic> json)
: fishMap = json.map(
(String k, dynamic v) => MapEntry(
k,
Fish.fromJson(v),
),
);
It's considered as an initializer list which runs before the constructor body, here you're calling the super that means the constructor of your Person class.
It's an initializer. This means the initializer is executed before the constructor body
How does Dart match the named parameters in a Constructor of a Class?
Example (which works) :
Class MyWidget {
final String a;
final String b;
MyWidget (
#required this.a,
#required this.b
)
#override // Yes, it's Flutter
Widget build(BuildContext context) {
return ....
}
}
/// Calling MyWidget
return MyWidget(
a: x,
b: y
)
This works as expected.
But in this setup I am forced to name the variable in MyWidget the same as the Named Parameter because the 'a' in the call is the same as the 'this.a' in the MyWidget.
What I would like is something like this:
Class MyWidget {
final String aaa;
final String bbb;
MyWidget (
#required a // And assign that value to this.aaa,
#required b // And assign that value to this.bbb
)
}
How do I assign the value of passed Named Parameter 'a' to local variable 'aaa'?
You have to trade off the simplicity of the this.xxx syntax like this:
class MyWidget {
final String aaa;
final String bbb;
MyWidget({a, b})
: aaa = a,
bbb = b;
}
I am new to flutter and getting type error. I am trying to use json automated serializations.
AFTER DOING SOME TWEAKS HERE IS HOW IT LOOKS LIKE
Here is how I am trying to get the data from api
Future getMyProduct() async {
final res = await http.get('url');
final data = json.decode(res.body);
BaseResponse req = new BaseResponse.fromJson(data);
return req;
}
My BaseResponse class looks like this
import 'package:dynamicapp/model/model.dart';
import 'package:json_annotation/json_annotation.dart';
part 'response.g.dart';
#JsonSerializable()
class BaseResponse extends Object {
final int id;
final int sellingPrice;
final int totalStock;
final String productName;
final String productDesc;
final List<Image> images;
BaseResponse(this.id, this.sellingPrice, this.totalStock, this.productName,
this.productDesc, this.images);
factory BaseResponse.fromJson(Map<String, dynamic> json) => _$BaseResponseFromJson(json);
Map<String, dynamic> toJson() => _$BaseResponseToJson(this);
}
#JsonSerializable()
class Image extends Object {
final int id;
final String image;
// final int product_id;
Image(this.id, this.image);
factory Image.fromJson(Map<String, dynamic> json) => _$ImageFromJson(json);
Map<String, dynamic> toJson() => _$ImageToJson(this);
}
Could anyone please help me with this. I am stuck here. Have been trying different methods but none working. Thank you.
It looks like data is a List<dynamic>, then data.map(someFunc).toList() will take each element of data pass it to someFunc and form it back into a list of the return type of someFunc (which you will presumably want to be BaseResponse). Which tells you that someFunc needs to be a function that takes dynamic and returns BaseResponse.
You'd want to write something like this:
final data = json.decode(res.body);
List<BaseResponse> responses =
data.map((j) => BaseResponse.fromJson(j)).toList();
So I have a #JsonSerializable class that's doing the job without an issue.
#JsonSerializable()
class BaseValue {
String id;
var value;
DateTime valueDate;
BaseValue({
this.id,
this.value,
this.valueDate
});
factory BaseValue.fromJson(Map<String, dynamic> json) => _$BaseValueFromJson(json);
Map<String, dynamic> toJson() => _$BaseValueToJson(this);
}
No I want to have the same fromJson toJson enabled for an extended ListBase class but can't find how to implement this.
class BaseValues<BaseValue> extends ListBase<BaseValue> {
final List<BaseValue> l = [];
BaseValues();
void set length(newLength) => l.length = newLength;
int get length => l.length;
BaseValue operator [](int index) => l[index];
void operator []=(int index, BaseValue value) => l[index] = value;
}
Maybe I need to use something else instead of ListBase.
Thanks in advance for any help provided.
It's possible, but it's not super easy. You need to create a custom TypeHelper to support your class.
Then, if you want to use pub run build_runner... you'll need to create a custom builder that instantiates an instance of JsonSerializableGenerator and include an instance of your TypeHelper.
There is a pending commit that will give you some more freedom here - https://github.com/dart-lang/json_serializable/commit/4f19d468bf05eed3e4a8ebc27244fc3b8d411dc9 – but you'll still have to handle the possible generic type args of BaseValues.