2
votes

Im still a bit new to Flutter / Dart and Ive struggled with parsing JSON for quite some time now. It seems like a daunting task to me, even though I think my JSON structure is not that complicated.

Your help would be greatly appreciated.

This is the JSON I want to parse:

{
   "predictionICL":{
      "openingTimeToday":"8:00 - 23:00",
      "openingTimeTomorrow":"8:00 - 23:00",
      "percentagesToday":[
         3,
         5,
         11,
         17,
         20,
         23,
         25,
         26,
         25,
         29,
         30,
         32,
         31,
         35,
         40,
         43,
         44,
         46,
         49,
         53,
         50,
         56,
         54,
         60,
         62,
         61,
         69,
         70,
         75,
         76,
         84,
         90,
         94,
         100,
         93,
         81,
         72,
         70,
         73,
         71,
         63,
         59,
         55,
         56,
         51,
         49,
         50,
         45,
         43,
         40,
         38,
         35,
         31,
         27,
         25,
         23,
         20,
         20,
         19,
         17,
         12,
         9,
         8,
         2,
         1
      ],
      "percentagesTomorrow":[ 
         0,
         0,
         1,
         7,
         14,
         20,
         22,
         21,
         21,
         22,
         20,
         25,
         27,
         31,
         30,
         31,
         32,
         33,
         30,
         34,
         35,
         33,
         35,
         37,
         39,
         40,
         40,
         39,
         38,
         40,
         41,
         38,
         34,
         37,
         34,
         35,
         33,
         32,
         31,
         30,
         33,
         30,
         31,
         30,
         29,
         30,
         27,
         28,
         26,
         23,
         20,
         19,
         16,
         17,
         15,
         12,
         10,
         7,
         5,
         1,
         1,
         0,
         0,
         0,
         0
      ]
   },
   "predictionRandwyck":{
      "openingTimeToday":"8:00 - 23:00",
      "openingTimeTomorrow":"8:00 - 23:00",
      "percentagesToday":[
         3,
         5,
         11,
         17,
         20,
         23,
         25,
         26,
         25,
         29,
         30,
         32,
         31,
         35,
         40,
         43,
         44,
         46,
         49,
         53,
         50,
         56,
         54,
         60,
         62,
         61,
         69,
         70,
         75,
         76,
         84,
         90,
         94,
         100,
         93,
         81,
         72,
         70,
         73,
         71,
         63,
         59,
         55,
         56,
         51,
         49,
         50,
         45,
         43,
         40,
         38,
         35,
         31,
         27,
         25,
         23,
         20,
         20,
         19,
         17,
         12,
         9,
         8,
         2,
         1
      ],
      "percentagesTomorrow":[
         0,
         0,
         1,
         7,
         14,
         20,
         22,
         21,
         21,
         22,
         20,
         25,
         27,
         31,
         30,
         31,
         32,
         33,
         30,
         34,
         35,
         33,
         35,
         37,
         39,
         40,
         40,
         39,
         38,
         40,
         41,
         38,
         34,
         37,
         34,
         35,
         33,
         32,
         31,
         30,
         33,
         30,
         31,
         30,
         29,
         30,
         27,
         28,
         26,
         23,
         20,
         19,
         16,
         17,
         15,
         12,
         10,
         7,
         5,
         1,
         1,
         0,
         0,
         0,
         0
      ]
   },
   "predictionTapijn":{
      "openingTimeToday":"8:00 - 23:00",
      "openingTimeTomorrow":"8:00 - 23:00",
      "percentagesToday":[
         3,
         5,
         11,
         17,
         20,
         23,
         25,
         26,
         25,
         29,
         30,
         32,
         31,
         35,
         40,
         43,
         44,
         46,
         49,
         53,
         50,
         56,
         54,
         60,
         62,
         61,
         69,
         70,
         75,
         76,
         84,
         90,
         94,
         100,
         93,
         81,
         72,
         70,
         73,
         71,
         63,
         59,
         55,
         56,
         51,
         49,
         50,
         45,
         43,
         40,
         38,
         35,
         31,
         27,
         25,
         23,
         20,
         20,
         19,
         17,
         12,
         9,
         8,
         2,
         1
      ],
      "percentagesTomorrow":[
         0,
         0,
         1,
         7,
         14,
         20,
         22,
         21,
         21,
         22,
         20,
         25,
         27,
         31,
         30,
         31,
         32,
         33,
         30,
         34,
         35,
         33,
         35,
         37,
         39,
         40,
         40,
         39,
         38,
         40,
         41,
         38,
         34,
         37,
         34,
         35,
         33,
         32,
         31,
         30,
         33,
         30,
         31,
         30,
         29,
         30,
         27,
         28,
         26,
         23,
         20,
         19,
         16,
         17,
         15,
         12,
         10,
         7,
         5,
         1,
         1,
         0,
         0,
         0,
         0
      ]
   },
   "message":"optionalmessageString"
} 

Its basically just three instances of the datatype LibraryPrediction and one optional Message string.

The datatype LibraryPrediction consists of one String "openingTimeToday", one String "openingTimeTomorrow" and two double Arrays "percentagesToday" and "percentagesTomorrow".

Right now, I am trying to parse the json from above from disk, as my Server is not running yet. This is my code so far:

I have one service file:

import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:test_app/models/predictions_update_model.dart';


PredictionsUpdate parseUpdate(String responseBody) {
  final jsonResponse = json.decode(responseBody).cast<Map<String, dynamic>>();

  PredictionsUpdate update = jsonResponse.map<PredictionsUpdate>((json) => PredictionsUpdate.fromJson(json));

  return update;

}

Future<PredictionsUpdate> fetchUpdate() async {

  final response = await rootBundle.loadString('lib/testJson/data.json');

  return parseUpdate(response);
}

And one model file:

class PredictionsUpdate {
  final LibraryPrediction predictionICL;
  final LibraryPrediction predictionRandwyck;
  final LibraryPrediction predictionTapijn;
  final String message;

  PredictionsUpdate({
    this.predictionICL,
    this.predictionRandwyck,
    this.predictionTapijn,
    this.message,
});

  factory PredictionsUpdate.fromJson(Map<String, dynamic> parsedJson){
    return PredictionsUpdate(
      predictionICL: LibraryPrediction.fromJson(parsedJson['predictionICL']),
      predictionRandwyck: LibraryPrediction.fromJson(parsedJson['predictionRandwyck']),
      predictionTapijn: LibraryPrediction.fromJson(parsedJson['predictionTapijn']),
      message: parsedJson['message'] as String,
    );
  }
}

class LibraryPrediction {
  final String openingTimeToday;
  final String openingTimeTomorrow;
  final List<double> percentagesToday;
  final List<double> percentagesTomorrow;

  LibraryPrediction({
    this.openingTimeToday,
    this.openingTimeTomorrow,
    this.percentagesToday,
    this.percentagesTomorrow,
  });

  factory LibraryPrediction.fromJson(Map<String, dynamic> json){
    return LibraryPrediction(
      openingTimeToday: json['openingTimeToday'] as String,
      openingTimeTomorrow: json['openingTimeTomorrow'] as String,
      percentagesToday: json['percentagesToday'] as List<double>,
      percentagesTomorrow: json['percentagesTomorrow'] as List<double>,
    );
  }
}

This is how I call the function:


Row(
              children: <Widget>[
                 RaisedButton(
                  child: Text('update'),
                  onPressed: () {
                    Future<PredictionsUpdate> futureUpdate = fetchUpdate();
                    futureUpdate.then((update)=> widget.currentNumbers = update)
                        .catchError((error) => print(error));
                  },
                ),
              ],
            ),

whenever I try to parse the JSON, I get the following error:

flutter: NoSuchMethodError: Class '_InternalLinkedHashMap<String, dynamic>' has no instance method 'cast' with matching arguments.
Receiver: _LinkedHashMap len:4
Tried calling: cast<Map<String, dynamic>>()
Found: cast<RK, RV>() => Map<RK, RV>

I have this feeling that the error originates somewhere when im trying to parse the double arrays "percentagesToday" or "percentagesTomorrow", but I can't say for sure and Im not able to get more clues from the error message.

I would be very grateful for any help in figuring out where I went wrong.

1

1 Answers

1
votes

You can copy paste run full code below
You can do like this List<double>.from(json["percentagesToday"].map((x) => x.toDouble())),

code snippet

factory LibraryPrediction.fromJson(Map<String, dynamic> json) =>
      LibraryPrediction(
        openingTimeToday: json["openingTimeToday"],
        openingTimeTomorrow: json["openingTimeTomorrow"],
        percentagesToday: List<double>.from(
            json["percentagesToday"].map((x) => x.toDouble())),
        percentagesTomorrow: List<double>.from(
            json["percentagesTomorrow"].map((x) => x.toDouble())),
      );
...   
futureUpdate.then((update) {
  print('${update.predictionIcl.openingTimeToday.toString()}');
  print('${update.message}');
  print('${update.predictionRandwyck.openingTimeTomorrow}');
}).catchError((error) => print(error)); 

output

I/flutter ( 7344): 8:00 - 23:00
I/flutter ( 7344): optionalmessageString
I/flutter ( 7344): 8:00 - 23:00

full code

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

PredictionsUpdate predictionsUpdateFromJson(String str) =>
    PredictionsUpdate.fromJson(json.decode(str));

class PredictionsUpdate {
  LibraryPrediction predictionIcl;
  LibraryPrediction predictionRandwyck;
  LibraryPrediction predictionTapijn;
  String message;

  PredictionsUpdate({
    this.predictionIcl,
    this.predictionRandwyck,
    this.predictionTapijn,
    this.message,
  });

  factory PredictionsUpdate.fromJson(Map<String, dynamic> json) =>
      PredictionsUpdate(
        predictionIcl: LibraryPrediction.fromJson(json["predictionICL"]),
        predictionRandwyck:
            LibraryPrediction.fromJson(json["predictionRandwyck"]),
        predictionTapijn: LibraryPrediction.fromJson(json["predictionTapijn"]),
        message: json["message"],
      );
}

class LibraryPrediction {
  String openingTimeToday;
  String openingTimeTomorrow;
  List<double> percentagesToday;
  List<double> percentagesTomorrow;

  LibraryPrediction({
    this.openingTimeToday,
    this.openingTimeTomorrow,
    this.percentagesToday,
    this.percentagesTomorrow,
  });

  factory LibraryPrediction.fromJson(Map<String, dynamic> json) =>
      LibraryPrediction(
        openingTimeToday: json["openingTimeToday"],
        openingTimeTomorrow: json["openingTimeTomorrow"],
        percentagesToday: List<double>.from(
            json["percentagesToday"].map((x) => x.toDouble())),
        percentagesTomorrow: List<double>.from(
            json["percentagesTomorrow"].map((x) => x.toDouble())),
      );
}

void main() {
  runApp(MyApp());
}

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

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  Future<PredictionsUpdate> fetchUpdate() async {
    String jsonString = '''
    {
   "predictionICL":{
      "openingTimeToday":"8:00 - 23:00",
      "openingTimeTomorrow":"8:00 - 23:00",
      "percentagesToday":[
         3,
         5,
         11,
         17,
         20,
         23,
         25,
         26,
         25,
         29,
         30,
         32,
         31,
         35,
         40,
         43,
         44,
         46,
         49,
         53,
         50,
         56,
         54,
         60,
         62,
         61,
         69,
         70,
         75,
         76,
         84,
         90,
         94,
         100,
         93,
         81,
         72,
         70,
         73,
         71,
         63,
         59,
         55,
         56,
         51,
         49,
         50,
         45,
         43,
         40,
         38,
         35,
         31,
         27,
         25,
         23,
         20,
         20,
         19,
         17,
         12,
         9,
         8,
         2,
         1
      ],
      "percentagesTomorrow":[ 
         0,
         0,
         1,
         7,
         14,
         20,
         22,
         21,
         21,
         22,
         20,
         25,
         27,
         31,
         30,
         31,
         32,
         33,
         30,
         34,
         35,
         33,
         35,
         37,
         39,
         40,
         40,
         39,
         38,
         40,
         41,
         38,
         34,
         37,
         34,
         35,
         33,
         32,
         31,
         30,
         33,
         30,
         31,
         30,
         29,
         30,
         27,
         28,
         26,
         23,
         20,
         19,
         16,
         17,
         15,
         12,
         10,
         7,
         5,
         1,
         1,
         0,
         0,
         0,
         0
      ]
   },
   "predictionRandwyck":{
      "openingTimeToday":"8:00 - 23:00",
      "openingTimeTomorrow":"8:00 - 23:00",
      "percentagesToday":[
         3,
         5,
         11,
         17,
         20,
         23,
         25,
         26,
         25,
         29,
         30,
         32,
         31,
         35,
         40,
         43,
         44,
         46,
         49,
         53,
         50,
         56,
         54,
         60,
         62,
         61,
         69,
         70,
         75,
         76,
         84,
         90,
         94,
         100,
         93,
         81,
         72,
         70,
         73,
         71,
         63,
         59,
         55,
         56,
         51,
         49,
         50,
         45,
         43,
         40,
         38,
         35,
         31,
         27,
         25,
         23,
         20,
         20,
         19,
         17,
         12,
         9,
         8,
         2,
         1
      ],
      "percentagesTomorrow":[
         0,
         0,
         1,
         7,
         14,
         20,
         22,
         21,
         21,
         22,
         20,
         25,
         27,
         31,
         30,
         31,
         32,
         33,
         30,
         34,
         35,
         33,
         35,
         37,
         39,
         40,
         40,
         39,
         38,
         40,
         41,
         38,
         34,
         37,
         34,
         35,
         33,
         32,
         31,
         30,
         33,
         30,
         31,
         30,
         29,
         30,
         27,
         28,
         26,
         23,
         20,
         19,
         16,
         17,
         15,
         12,
         10,
         7,
         5,
         1,
         1,
         0,
         0,
         0,
         0
      ]
   },
   "predictionTapijn":{
      "openingTimeToday":"8:00 - 23:00",
      "openingTimeTomorrow":"8:00 - 23:00",
      "percentagesToday":[
         3,
         5,
         11,
         17,
         20,
         23,
         25,
         26,
         25,
         29,
         30,
         32,
         31,
         35,
         40,
         43,
         44,
         46,
         49,
         53,
         50,
         56,
         54,
         60,
         62,
         61,
         69,
         70,
         75,
         76,
         84,
         90,
         94,
         100,
         93,
         81,
         72,
         70,
         73,
         71,
         63,
         59,
         55,
         56,
         51,
         49,
         50,
         45,
         43,
         40,
         38,
         35,
         31,
         27,
         25,
         23,
         20,
         20,
         19,
         17,
         12,
         9,
         8,
         2,
         1
      ],
      "percentagesTomorrow":[
         0,
         0,
         1,
         7,
         14,
         20,
         22,
         21,
         21,
         22,
         20,
         25,
         27,
         31,
         30,
         31,
         32,
         33,
         30,
         34,
         35,
         33,
         35,
         37,
         39,
         40,
         40,
         39,
         38,
         40,
         41,
         38,
         34,
         37,
         34,
         35,
         33,
         32,
         31,
         30,
         33,
         30,
         31,
         30,
         29,
         30,
         27,
         28,
         26,
         23,
         20,
         19,
         16,
         17,
         15,
         12,
         10,
         7,
         5,
         1,
         1,
         0,
         0,
         0,
         0
      ]
   },
   "message":"optionalmessageString"
}
    ''';

    //final response = await rootBundle.loadString('lib/testJson/data.json');
    final http.Response response = http.Response(jsonString, 200);
    PredictionsUpdate payload = predictionsUpdateFromJson(response.body);
    return payload;
  }

  void _incrementCounter() {
    Future<PredictionsUpdate> futureUpdate = fetchUpdate();
    futureUpdate.then((update) {
      print('${update.predictionIcl.openingTimeToday.toString()}');
      print('${update.message}');
      print('${update.predictionRandwyck.openingTimeTomorrow}');
    }).catchError((error) => print(error));

    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}