How can I use a Variable of JSON data in Flutter (not a listview)

2.3k views Asked by At

I'm asking after looking into a lot of examples and similar questions, but I can't get my head around. I just want to get certain data from an id in a json map into Flutter. What I receive via php is 2 strings of JSON (it's correct JSON I've checked with jsonlint):

[{"id":1,"firstname":"John","surname":"Wick","guitarbrand":"Ibanez","votes":15,"pickups":2},{"id":2,"firstname":"Elvis","surname":"Presley","guitarbrand":"LesPaul","votes":10,"pickups":1},{"id":3,"firstname":"Kirk","surname":"Hammet","guitarbrand":"HarleyBenton","votes":9,"pickups":3}]


{"id":1,"firstname":"John","surname":"Wick","guitarbrand":"Ibanez","votes":15,"pickups":2}

I'm using a separate Dart file which I import into main.dart:

    import 'dart:convert';

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

Future<Dayplay> fetchDayplay() async {
  final resp1 = await http.get(Uri.parse('http://somewhere.com/getdayentries.php'));
  if (resp1.statusCode == 200) {
    // If the server did return a 200 OK response,
    // then parse the JSON.
    print('Response body: ${json.decode((resp1.body))}');
    return Dayplay.fromJson(jsonDecode(resp1.body));
  } else {
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load album');
  }
}


Future<Winner> fetchWinner() async {
  final resp2 = await http.get(Uri.parse('http://somewhere.com/getwinner.php'));
  if (resp2.statusCode == 200) {
    // If the server did return a 200 OK response,
    // then parse the JSON.
    print('Response body: ${json.decode((resp2.body))}');
    return Winner.fromJson(jsonDecode(resp2.body));
  } else {
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load album');
  }
}

class Dayplay {
  int? _id;
  String? _firstname;
  String? _surname;
  String? _guitarbrand;
  int? _votes;
  int? _pickups;

  Dayplay(
      {int? id,
        String? firstname,
        String? surname,
        String? guitarbrand,
        int? votes,
        int? pickups}) {
    if (id != null) {
      this._id = id;
    }
    if (firstname != null) {
      this._firstname = firstname;
    }
    if (surname != null) {
      this._surname = surname;
    }
    if (guitarbrand != null) {
      this._guitarbrand = guitarbrand;
    }
    if (votes != null) {
      this._votes = votes;
    }
    if (pickups != null) {
      this._pickups = pickups;
    }
  }

  int? get id => _id;
  set id(int? id) => _id = id;
  String? get firstname => _firstname;
  set firstname(String? firstname) => _firstname = firstname;
  String? get surname => _surname;
  set surname(String? surname) => _surname = surname;
  String? get guitarbrand => _guitarbrand;
  set guitarbrand(String? guitarbrand) => _guitarbrand = guitarbrand;
  int? get votes => _votes;
  set votes(int? votes) => _votes = votes;
  int? get pickups => _pickups;
  set pickups(int? pickups) => _pickups = pickups;

  Dayplay.fromJson(Map<String, dynamic> json) {
    _id = json['id'];
    _firstname = json['firstname'];
    _surname = json['surname'];
    _guitarbrand = json['guitarbrand'];
    _votes = json['votes'];
    _pickups = json['pickups'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this._id;
    data['firstname'] = this._firstname;
    data['surname'] = this._surname;
    data['guitarbrand'] = this._guitarbrand;
    data['votes'] = this._votes;
    data['pickups'] = this._pickups;
    return data;
  }
}

class Winner {
  int? _id;
  String? _firstname;
  String? _surname;
  String? _guitarbrand;
  int? _votes;
  int? _pickups;

  Winner(
      {int? id,
        String? firstname,
        String? surname,
        String? guitarbrand,
        int? votes,
        int? pickups}) {
    if (id != null) {
      this._id = id;
    }
    if (firstname != null) {
      this._firstname = firstname;
    }
    if (surname != null) {
      this._surname = surname;
    }
    if (guitarbrand != null) {
      this._guitarbrand = guitarbrand;
    }
    if (votes != null) {
      this._votes = votes;
    }
    if (pickups != null) {
      this._pickups = pickups;
    }
  }

  int? get id => _id;
  set id(int? id) => _id = id;
  String? get firstname => _firstname;
  set firstname(String? firstname) => _firstname = firstname;
  String? get surname => _surname;
  set surname(String? surname) => _surname = surname;
  String? get guitarbrand => _guitarbrand;
  set guitarbrand(String? guitarbrand) => _guitarbrand = guitarbrand;
  int? get votes => _votes;
  set votes(int? votes) => _votes = votes;
  int? get pickups => _pickups;
  set pickups(int? pickups) => _pickups = pickups;

  Winner.fromJson(Map<String, dynamic> json) {
    _id = json['id'];
    _firstname = json['firstname'];
    _surname = json['surname'];
    _guitarbrand = json['guitarbrand'];
    _votes = json['votes'];
    _pickups = json['pickups'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this._id;
    data['firstname'] = this._firstname;
    data['surname'] = this._surname;
    data['guitarbrand'] = this._guitarbrand;
    data['votes'] = this._votes;
    data['pickups'] = this._pickups;
    return data;
  }
}

And this is partly the Main.dart where I need the data:

    import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:fiveupmusic/getdata.dart';

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  var idctl = "";
  late bool error, sending, success;
  late Future<Dayplay> futureDayplay;
  late Future<Winner> futureWinner; 
  
  @override
  void initState() {
    futureDayplay = fetchDayplay();
    futureWinner = fetchWinner();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: FutureBuilder(
        future: futureDayplay,
        builder: (BuildContext context, AsyncSnapshot snapshot) {
         if (snapshot.hasData) {
            return Text(snapshot.data!.bandname);
          } else if (snapshot.hasError) {
            return Text('${snapshot.error}');
          }
          print("snapshot");
          print(snapshot.data);
          return SafeArea(
                child: SingleChildScrollView(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: <Widget>[
                      Image.asset('assets/images/top_logo_320x40.jpg'),
                      Center(child: Text('Result: (how do I get the variable data here?)',
                        style: TextStyle(
                          color: Colors.lightBlue[100],
                        ),
                      )),..............

-Can I use 2 Futures in the same FutureBuilder? I need the data from both JSON strings

-How can I retrieve data from a certain id?

I get to see the data via the print command and I get this:

E/flutter (27453): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'

E/flutter (27130):  <asynchronous suspension>

I don't understand why after the first JSON data it gives that error After the 2nd received string there is no error. I don't have any other errors in Android Studio.

Thanks for more insight on how to solve this.

1

There are 1 answers

1
user18309290 On BEST ANSWER

One way to do this is use Future.wait wait both calls. data is then the list of results. Use firstWhere to find object from the list.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: FutureBuilder(
            future: Future.wait([fetchPosts(), fetchUser()]),
            builder: (context, snapshot) {
              if (snapshot.hasError) {
                return Text('${snapshot.error}');
              } else if (snapshot.hasData) {
                final posts = (snapshot.data as List)[0] as List<dynamic>;
                final user = (snapshot.data as List)[1];
                final userId = user['id'];
                final post = posts.firstWhere((post) => post['userId'] == userId);
                return Text('$post');
              } else {
                return const Text('Loading ...');
              }
            }
          )
        ),
      ),
    );
  }
  
  Future<List<dynamic>> fetchPosts() async {
    final resp1 = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
    if (resp1.statusCode == 200) {
      return json.decode((resp1.body));
    } else {
      throw Exception('Failed to load');
    }
  }

  Future<Map<String,dynamic>> fetchUser() async {
    final resp2 = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users/1'));
    if (resp2.statusCode == 200) {
      return json.decode((resp2.body));
    } else {
      throw Exception('Failed to load');
    }
  }
}