Home > Mobile >  Problem when converting a JSON list in Flutter (My model is not a subtype of type 'Map<Strin
Problem when converting a JSON list in Flutter (My model is not a subtype of type 'Map<Strin

Time:10-10

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 JSON : enter image description here

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 ?? []);
}
  • Related