I have a problem when converting my json
to my model in Flutter.
I would like to access the 'body' list in order to then display the list containing 'children'.
I am trying to do it the way I already know and never failed me, now I have an exception:
type 'MenuBodyData' is not a subtype of type 'Map<String, dynamic>' in type cast".
Maybe someone knows a solution to this problem?
My model :
@JsonSerializable()
class MenuBodyData {
/// const constructor of MenuBodyData model
const MenuBodyData({
required this.type,
required this.shrinkWrap,
required this.children,
required this.floatingActionButtons,
});
/// returns MenuBodyData from Json
factory MenuBodyData.fromJson(Map<String, dynamic> json) =>
_$MenuBodyDataFromJson(json);
/// menu type
final String? type;
/// menu status
final bool? shrinkWrap;
/// menu children
final List<ChildrenBodyData>? children;
/// menu floatingActionButtons
final bool? floatingActionButtons;
/// return json based on MenuBodyData
Map<String, dynamic> toJson() => _$MenuBodyDataToJson(this);
}
My code :
/// returns menu body
Future<List<ChildrenBodyData>> getChildren() async {
final requestBody = {
'DatabaseHandle': 'WUWER_TESTY',
'Operator': userLogin,
'Password': userPassword,
'ServiceName': 'Soneta.Dps.Wms.Api.Interfaces.IMws, Soneta.Dps.Wms.Api',
'MethodName': 'GetMenuList',
'MethodArgs': null,
};
final uri = Uri.https(
apiBaseUrl,
apiBaseMethods,
);
final response = await _httpClient.post(
uri,
body: jsonEncode(requestBody),
headers: headers,
);
final exception = _exception(response);
if (exception != null) {
throw RequestException(exceptionMessage: exception);
}
final bodyItems = <MenuBodyData>[];
final childrenItems = <ChildrenBodyData>[];
try {
final dynamic jsonBody =
(_resultInstance(response) as Map<String, dynamic>)['body'];
for (final bodyItem in jsonBody) {
final item = MenuBodyData.fromJson(bodyItem as Map<String, dynamic>);
bodyItems.add(item);
}
for (final jsonChildren in bodyItems) {
final children =
ChildrenBodyData.fromJson(jsonChildren as Map<String, dynamic>);
childrenItems.add(children);
}
return childrenItems;
} catch (e) {
throw MenuItemDeserializationFailure();
}
}
My ChildrenBodyData model :
@JsonSerializable()
class ChildrenBodyData {
/// const constructor of ChildrenBodyData model
const ChildrenBodyData({
required this.type,
required this.backgroundColor,
required this.margin,
required this.width,
required this.name,
required this.id,
required this.textAlign,
required this.onPressed,
});
/// returns ChildrenBodyData from Json
factory ChildrenBodyData.fromJson(Map<String, dynamic> json) =>
_$ChildrenBodyDataFromJson(json);
/// children type
final String? type;
/// children id
final int? id;
/// children backgroundColor
final int? backgroundColor;
/// children margin
final double? margin;
/// children width
final double? width;
/// children name
final String? name;
/// text textAlign
final String? textAlign;
/// text textAlign
final List<OnPressedData>? onPressed;
/// return json based on ChildrenBodyData
Map<String, dynamic> toJson() => _$ChildrenBodyDataToJson(this);
}
CodePudding user response:
To access body's children you need to change this:
for (final jsonChildren in bodyItems) {
final children =
ChildrenBodyData.fromJson(jsonChildren as Map<String, dynamic>);
childrenItems.add(children);
}
to this:
for (final item in bodyItems) {
final children = (item["children"] as List).map((e) => ChildrenBodyData.fromJson(e)).toList();
childrenItems.addAll(children);
}
I don't know if you handle this in you model class or not. but if not you can do up, but if you handle children in your model class you just need this:
for (final item in bodyItems) {
childrenItems.addAll(item.children);
}
and for access to childrenItems value you can do this:
print("name = ${childrenItems[0].name}");
CodePudding user response:
bodyItems
is a list of MenuBodyData
. You iterate over it at
for (final jsonChildren in bodyItems) {
So each jsonChildren
is a MenuBodyData
object. Yet, you try to cast it to a map when doing
jsonChildren as Map<String, dynamic>
You can't just do that. You probably want to do this instead:
jsonChildren.toJson()
EDIT:
On second thought, I think you actually want to do this. Your MenuBodyData
objects should already have a list of ChildrenBodyData
for (final jsonChildren in bodyItems) {
childrenItems.addAll(jsonChildren.children ?? []);
}