Parsing JSON With A Nested, Dynamic Type
Let's assume I have 3 data classes (which in reality may be many more). Class A
or class B
shall be wrapped in class Wrap
with a data type identifier. This shall allow using the same process inside the app for any data type provided by the json interface.
class Wrap{
int id;
List<dynamic> dataSet;
Wrap({required this.id, required this.dataSet});
}
class A{
int a=0;
A({this.a});
}
class B{
bool b=true;
B({this.b});
}
My aim was to use a map getDataType = {0: A, 1: B};
and then to parse the nested Json with
dataSets: List<dynamic>.from(json["dataSets"].map((d) => getDataType[json["id"].fromJson(d)).toList();
But unfortunately this already fails when trying to access a class method from the variable containing the type
class A{
int i=0; A({i});
factory A.test(int i) => A(2*i);
}
main() {
final t = A;
final x = t.test(2);
}
Anyone with a smart idea how to achieve this?
The rational behind this unorthodox data structure is: I have a data manager in the business logic layer that triggers different UIs depending on some events, coming from a different logic. The manager then fetches the specific data for the UI. To streamline this, the same repository with the same functions shall be used. However, the repository function uses a different database table depending on the UI.
UPDATE: Most basic example json:
{
"id": 0,
"data": [
{
"problemId": 0,
"level": 2
}
]
}
Answer
First of all create an abstact class for datasets
abstract class Dataset {
const Dataset();
factory Dataset.fromMap(Map<String, dynamic> map, int type) {
switch (type) {
case 0:
return ADataset.fromMap(map);
case 1:
return BDataset.fromMap(map);
default:
throw Exception("Class with id $type couldn't be found");
}
}
}
and replace List<dynamic> dataSet;
in Wrap
class with List<Dataset> dataSet;
Now you can simply create dataset classes by extending this Dataset
class
class ADataset extends Dataset {
final int fieldA;
ADataset(
this.fieldA,
);
factory ADataset.fromMap(Map<String, dynamic> map) {
return ADataset(map['int field']);
}
}
class BDataset extends Dataset {
final String fieldB;
BDataset(
this.fieldB,
);
factory BDataset.fromMap(Map<String, dynamic> map) {
return BDataset(map['string field']);
}
}
So now all you need to do is
dataSets: List<Dataset>.from(map['datasets'].map(
(dataset) => Dataset.fromMap(dataset, map['type']),
));
Related Questions
- → I can't convert Json to string [OctoberCms]
- → Uncaught TypeError Illegal invocation when send FormData to ajax
- → Laravel Send URL with JSON
- → how to write react component to construct HTML DOM
- → AJAX folder path issue
- → Chaining "Count of Columns" of a Method to Single Query Builder
- → Laravel - bindings file for repositories
- → Good solution to work with rest-api like SPA with redux?
- → getting the correct record in Angular with a json feed and passed data
- → Transformer usage on laravel/dingo API
- → Google options Page not saving - Javascript
- → Ember.js JSON API confusion
- → How can I query Firebase for an equalTo boolean parameter?