0

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.

3
  • The first string is a list of Map<String, dynamic> while the second string is just a Map<String, dynamic>. You would need to loop through each element in your first string and then turn them into a map. Commented May 8, 2022 at 16:38
  • try print runtimeType of your variable before the error appear, that error because your variable is list and you force it to map Commented May 9, 2022 at 2:22
  • I'm getting List<dynamic> runtimetype: AsyncSnapshot<List<Object>> and _InternalLinkedHashMap<String, dynamic> Commented May 16, 2022 at 20:16

1 Answer 1

1

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');
    }
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much! This helped tremendous! I looked over a tiny thing. Now the data is returned to the builder. Up to the next step extracting the data and assign to variables.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.