John Mcfetridge
John Mcfetridge

Reputation: 1197

flutter serialize son to list objects throws exception

I have a .net server web api call that I am trying to port the client part to Flutter from Xamarin. mostly impressed with flutter/Dart except the json serialization/deserialization is a pain! my api returns a list of exercise routines that have embedded list of machines. this is pretty simp and normal stuff. my generated JSON looks like :

[
{"id":1,"
Name":"back",
"userid":1,
"cloned":0,
"Machines":
    [
        {"machineid":2,
        "Name":"Leg Extension","PictureUrl":"https://l},
        {"machineid":3,"Name":"yoga ball","PictureUrl":"https://
         }

I originally tried the manual approach with dart.convert and things worked for my serializing a list of routines. however then I decided to use the code generation as described here my code thru following exception when I called jsonDecode:

type 'List' is not a subtype of type 'Map'

my flutter UI code looks like:

_fetchData() async {
setState(() {
  isLoading = true;
});

final response =
await http.get("http://fitnesspal.azurewebsites.net/api/routines");
if (response.statusCode == 200) {
 // list = (json.decode(response.body) as List)
 //     .map((data) => new Routine.fromJson(data))
  //    .toList();
//  final jsonResponse = json.decode(response.body);
  try {
    String json1 = response.body;
    Map map1 = jsonDecode(json1);
    var test = Routine.fromJson(map1);
  }
  catch (e) {
    print(e.toString());
  }


  setState(() {
    isLoading = false;
  });
} else {
  throw Exception('Failed to load photos');
}

}

import 'package:json_annotation/json_annotation.dart';
import 'package:fitnesspal/Models/Machine.dart';
part 'Routine.g.dart';

@JsonSerializable(nullable: false)
class Routine{
 final int id;
  final String name;
 @JsonKey(name: 'Machines')
 List<Machine> Machines;

 Routine({this.id,this.name,this.Machines});

 factory Routine.fromJson(Map<String, dynamic> json) =>
  _$RoutineFromJson(json);
 Map<String, dynamic> toJson() => _$RoutineToJson(this);

}

I followed the described code generation steps

Upvotes: 1

Views: 2407

Answers (2)

John Mcfetridge
John Mcfetridge

Reputation: 1197

sorry the above was DFU error with stackoverflow. your idea worked but to get the list of routines that I wanted I ended up with:

list = (jsonDecode(response.body) as List)
     .map((data) => new Routine.fromJson(data))
     .toList();

I then use the routine name in my listBuilder and looks good so feeling pretty good but then I need to pass the embedded machine list to my list of machines widget. so I add a stateful widget called MachineList as follows: notice I setup my constructor to accept the List

class MachineList extends StatefulWidget {
final List<Machine> machines;
MachineList({Key key, this.machines}) : super(key: key);
@override
_MachineListState createState() => _MachineListState(machines);

}

then back in main.dart I want to navigate in the list item ontap :

Navigator.push(
                  context,
                  MaterialPageRoute(
                     builder: (context) => MachineList(
                         machines: list[index].machines)
                  )
             );

lib/main.dart:122:82: Error: The argument type 'dart.core::List<#lib1::Machine>' can't be assigned to the parameter type 'dart.core::List<#lib2::Machine>

OMG where is it getting lib2 from

**** found my issue a case mismatch on the import In Dart, two libraries are the same if, and only if, they are imported using the same URI. If two different URIs are used, I had .../Models/. and ../models painful learning experience as did not realize Dart was so sensitive as to used to c#

Upvotes: 0

diegoveloper
diegoveloper

Reputation: 103401

This doesn't work because json1 is a List of objects, not a Map.

 Map map1 = jsonDecode(json1);

Try using this :

List list = jsonDecode(json1);

And get the first element just for testing (in a real scenario you will have to loop the list)

  var test = Routine.fromJson(list[0]);

Upvotes: 1

Related Questions