skip to Main Content

I’m currently learning Flutter by watching video-course on Udemy.

Following the speaker step-by-step i ended up with an error which i can’t get rid of.

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter JSON demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late Future<OfficesList> officesList;

  @override
  void initState() {
    super.initState();
    officesList = getOfficesList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Manual JSON serialization'),
        centerTitle: true,
      ),
      body: FutureBuilder<OfficesList>(
        future: officesList,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              itemCount: snapshot.data?.offices.length,
              itemBuilder: (context, index) {
                return Card(
                  child: ListTile(
                    title: Text('${snapshot.data?.offices[index].name}'),
                    subtitle: Text('${snapshot.data?.offices[index].adress}'),
                    leading:
                        Image.network('${snapshot.data?.offices[index].image}'),
                    isThreeLine: true,
                  ),
                );
              },
            );
          } else if (snapshot.hasError) {
            return Text(snapshot.error.toString());
          } else {
            return const Text('null');
          }
          // return const Center(
          //   child: CircularProgressIndicator(),
          // );
        },
      ),
    );
  }
}

    import 'dart:convert';
import 'package:http/http.dart' as http;

class OfficesList {
  List<Office> offices;
  OfficesList({required this.offices});

  factory OfficesList.fromJson(Map<String, dynamic> json) { 
    var officesJson = json['offices'] as List;    // <-- the problem might be somewhere here 
    List<Office> officesList =
        officesJson.map((i) => Office.fromJson(i)).toList as List<Office>;

    return OfficesList(
      offices: officesList,
    );
  }
}

class Office {
  String? name;
  String? adress;
  String? image;

  Office({
    required this.name,
    required this.adress,
    required this.image,
  });

  factory Office.fromJson(Map<String, dynamic> json) {
    return Office(
        name: json['name'] as String,
        adress: json['adress'] as String,
        image: json['image'] as String);
  }
}

Future<OfficesList> getOfficesList() async {
  const url = 'https://about.google/static/data/locations.json';
  final response = await http.get(Uri.parse(url));

  if (response.statusCode == 200) {
    return OfficesList.fromJson(json.decode(response.body));
  } else {
    throw Exception('Error: ${response.reasonPhrase}');
  }
}


Here's error i get

His way of writing the code might be the problem, cuz videos are kinda old (approx. 1-2 years).

I googled the problem, tried to add some arguments to List and so on, but it didn’t help.

Will be very grateful for any advice.

3

Answers


  1. Chosen as BEST ANSWER

    The problem was String named adress in Office constructor. Key from JSON is named address.
    So it was returning null, because there's no key named adress

    class Office {
      String? name;
      String? adress;
      String? image;
    
      Office({
        required this.name,
        required this.adress, // <-- "adress" instead of "address
        required this.image,
      });
    
      factory Office.fromJson(Map<String, dynamic> json) {
        return Office(
            name: json['name'] as String,
            adress: json['adress'] as String, // <-- "adress" instead of "address
            image: json['image'] as String);
      }
    }
    

  2. In OfficesList.fromJson you need to change toList to toList() so that you’re calling the function and actually getting the list.

    class OfficesList {
      List<Office> offices;
      OfficesList({required this.offices});
    
      factory OfficesList.fromJson(Map<String, dynamic> json) { 
        var officesJson = json['offices'] as List;
    
        List<Office> officesList =
            officesJson.map((i) => Office.fromJson(i)).toList() as List<Office>;
        //                                                   ^^   
    
        return OfficesList(
          offices: officesList,
        );
      }
    }
    
    Login or Signup to reply.
  3. Just remove the as List<Office> here is an example.

    var officeJson = json.encode([
       {"name": "test1", "address": "address1", "image": "image1"},
       {"name": "test2", "address": "address2", "image": "image2"}
    ]);
    
    List<dynamic> decodedOfficeJson = jsonDecode(officeJson);
    
    List<Office> officesList = decodedOfficeJson.map((i) => Office.fromJson(i)).toList();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search