Search code examples
jsonflutterdartflutter-listview

Flutter: JSON data , list under list


I have JSON data file that looks like this, as you can see the email is a list itself:

[
    {
        "index": 0,
        "about": "text text text",
        "email": [
            "[email protected]",
            "[email protected]",
        ],
        "name": "sample name",
        "picture": "https://kdjfksfjsdklfs.com"
    },
    {
        "index": 1,
        "about": "text text text",
        "email": [
            "[email protected]",
            "[email protected]",
        ],
        "name": "sample name ",
        "picture": "https://kdjfksfjsdklfs.com"
    },
    {
        "index": 2,
        "about": "text text text",
        "email": [
            "[email protected]",
            "[email protected]",
        ],
        "name": "sample name",
        "picture": "https://kdjfksfjsdklfs.com"
    }
]

My code is the following, which is basically a listview builder that gets data from the above JSON. Now when the list is clicked it navigate to the next page where I need to show details of this user.

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Users'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

Future _data;

class _MyHomePageState extends State<MyHomePage> {
  Future<List<User>> _getUsers() async {
    var data =
        await DefaultAssetBundle.of(context).loadString("assets/test.json");

    var jsonData = json.decode(data);

    List<User> users = [];

    for (var u in jsonData) {
      User user =
          User(u["index"], u["about"], u["name"], u["email"], u["picture"]);

      users.add(user);
    }

    print(users.length);

    return users;
  }

  @override
  void initState() {
    super.initState();
    _data = _getUsers();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: Container(
        child: FutureBuilder(
          future: _data,
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            print(snapshot.data);
            if (snapshot.data == null) {
              return Container(child: Center(child: Text("Loading...")));
            } else {
              return ListView.builder(
                itemCount: snapshot.data.length,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                    leading: CircleAvatar(
                      backgroundImage:
                          NetworkImage(snapshot.data[index].picture),
                    ),
                    title: Text(snapshot.data[index].name),
                    // subtitle: Text(snapshot.data[index].email),
                    onTap: () {
                      Navigator.push(
                          context,
                          new MaterialPageRoute(
                              builder: (context) =>
                                  DetailPage(snapshot.data[index])));
                    },
                  );
                },
              );
            }
          },
        ),
      ),
    );
  }
}

class DetailPage extends StatelessWidget {
  final User user;

  DetailPage(this.user);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(user.name),
      ),
      body: Container(
        child: Text(user.about),
      ),
    );
  }
}

class User {
  final int index;
  final String about;
  final String name;
  final String email;
  final String picture;

  User(this.index, this.about, this.name, this.email, this.picture);
}

I wanted to create Listview Builder in the second page for name and the email so that all the emails listed under the name.

can someone help I am not able to generate the second page list especially the email list.


Solution

  • Just check out this example and let me know if it works for you:

    import 'package:flutter/material.dart';
    import 'dart:async';
    import 'dart:convert';
    
    import 'package:json_parsing_example/models.dart';
    
    // To parse this JSON data, do
    //
    //     final user = userFromJson(jsonString);
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Flutter Demo',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(title: 'Users'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    
    Future _data;
    
    class _MyHomePageState extends State<MyHomePage> {
      Future<List<User>> _getUsers() async {
        var data =
            await DefaultAssetBundle.of(context).loadString("json/parse.json");
    
        return userFromJson(data);
      }
    
      @override
      void initState() {
        super.initState();
        _data = _getUsers();
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(widget.title),
          ),
          body: Container(
            child: FutureBuilder<List<User>>(
              future: _data,
              builder: (BuildContext context, AsyncSnapshot snapshot) {
                print(snapshot.data);
                if (snapshot.data == null) {
                  return Container(child: Center(child: Text("Loading...")));
                } else {
                  return ListView.builder(
                    itemCount: snapshot.data.length,
                    itemBuilder: (BuildContext context, int index) {
                      return ListTile(
                        leading: CircleAvatar(
                          backgroundImage:
                              NetworkImage(snapshot.data[index].picture),
                        ),
                        title: Text(snapshot.data[index].name),
                        // subtitle: Text(snapshot.data[index].email),
                        onTap: () {
                          Navigator.push(
                              context,
                              new MaterialPageRoute(
                                  builder: (context) =>
                                      DetailPage(snapshot.data[index])));
                        },
                      );
                    },
                  );
                }
              },
            ),
          ),
        );
      }
    }
    
    class DetailPage extends StatefulWidget {
      final User user;
    
      DetailPage(this.user);
    
      @override
      _DetailPageState createState() => _DetailPageState();
    }
    
    class _DetailPageState extends State<DetailPage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.user.name),
          ),
          body: Container(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(
                    widget.user.name,
                    style: TextStyle(fontSize: 20),
                  ),
                ),
                ListView.builder(
                  shrinkWrap: true,
                  itemCount: widget.user.email.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Card(
                        child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text(widget.user.email[index]),
                    ));
                  },
                ),
              ],
            ),
          ),
        );
      }
    }
    
    
    

    Your model class :

    // To parse this JSON data, do
    //
    //     final user = userFromJson(jsonString);
    
    import 'dart:convert';
    
    List<User> userFromJson(String str) => List<User>.from(json.decode(str).map((x) => User.fromJson(x)));
    
    String userToJson(List<User> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
    
    class User {
        User({
            this.index,
            this.about,
            this.email,
            this.name,
            this.picture,
        });
    
        int index;
        String about;
        List<String> email;
        String name;
        String picture;
    
        factory User.fromJson(Map<String, dynamic> json) => User(
            index: json["index"],
            about: json["about"],
            email: List<String>.from(json["email"].map((x) => x)),
            name: json["name"],
            picture: json["picture"],
        );
    
        Map<String, dynamic> toJson() => {
            "index": index,
            "about": about,
            "email": List<dynamic>.from(email.map((x) => x)),
            "name": name,
            "picture": picture,
        };
    }