Alvin Heng
Alvin Heng

Reputation: 35

Flutter: How to parse json nested map on dart

Here is the json file that i want to parse:

{
    "Meta Data": {
        "1. Information": "Weekly Adjusted Prices and Volumes",
        "2. Symbol": "MSFT",
        "3. Last Refreshed": "2020-03-25",
        "4. Time Zone": "US/Eastern"
    },
    "Weekly Adjusted Time Series": {
        "2020-03-25": {
            "1. open": "137.0100",
            "2. high": "154.3300",
            "3. low": "132.5200",
            "4. close": "146.9200",
            "5. adjusted close": "146.9200",
            "6. volume": "235583286",
            "7. dividend amount": "0.0000"
        },
        "2020-03-20": {
            "1. open": "140.0000",
            "2. high": "150.1500",
            "3. low": "135.0000",
            "4. close": "137.3500",
            "5. adjusted close": "137.3500",
            "6. volume": "421347734",
            "7. dividend amount": "0.0000"
        },
}

I just wanted to get the date, open, and close. I tried finding stuff online but still was unable to do so.

Here is my TimeSeries class:

class TimeSeries {
  final String date;
  final double open;
  final double close;

  TimeSeries({this.date, this.open, this.close});

  factory TimeSeries.fromJson(Map<String, dynamic> json) {
    return TimeSeries(
      date: json[''],
      open: double.parse(json['1. open']),
      close: double.parse(json['4. close']),
    );
  }
}

And these are my function for now:

Future getTimeSeries(String stock) async {
    print("Starting get request");
    http.get("https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&apikey=demo").then((res){
      print("received response.");
      var resObj = json.decode(res.body);
     }).catchError((e) {
      print("Failed to get response.");
    });
  }

Upvotes: 2

Views: 1644

Answers (3)

Alexander Mazuruk
Alexander Mazuruk

Reputation: 31

I'd suggest to use this library https://github.com/k-paxian/dart-json-mapper

Of course if you don't like to hardcode .fromJson methods for all your model classes manually and having fun with debugging & supporting them later.

Upvotes: 0

Albert221
Albert221

Reputation: 7182

You may want to do some mapping here. Your TimeSeries class is enough, but you need to tweak your getTimeSeries function. Firstly, you may want to change its return type to return a Future with a List<TimeSeries>, because you'll be getting a list of those.

Inside the then callback of your HTTP call you want to firstly get inside the JSON map you have data in, so in that case it's resObj['Weekly Adjusted Time Series']. Then, run map on this and here is the place where you want to instantiate TimeSeries (I also used final instead of var - it's just a good practise to use it where you don't need var):

final resObj = json.decode(res.body);

return resObj.map((date, fields) {
  return TimeSeries(DateTime.parse(date), fields['1. open'], fields['4. close']);
});

IMO TimeSeries.fromJson won't help here, because you don't get the date field from this inside map in your JSON.

Your whole new code would look like this:

class TimeSeries {
  final String date;
  final double open;
  final double close;

  TimeSeries({this.date, this.open, this.close});
}

Future<List<TimeSeries>> getTimeSeries(String stock) async {
  print("Starting get request");

  return http.get("https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&apikey=demo").then((res){
    print("received response.");
    final resObj = json.decode(res.body);

    return resObj.map((date, fields) {
      return TimeSeries(date, fields['1. open'], fields['4. close']);
    });
   }).catchError((e) {
    print("Failed to get response.");
  });
}

Upvotes: 2

Lo&#239;c Fonkam
Lo&#239;c Fonkam

Reputation: 2340

Try this.

class TimeSeries {
  final String date;
  final double open;
  final double close;

  TimeSeries({this.date, this.open, this.close});

  factory TimeSeries.fromJson(Map<String, dynamic> json, String indexDate) {
    return TimeSeries(
      date: indexDate,
      open: double.parse(json["Weekly Adjusted Time Series"][indexDate]['1. open']),
      close: double.parse(json["Weekly Adjusted Time Series"][indexDate]['4. close']),
    );
  }
}

And you can call the constructor as follows

List<TimeSeries> datesList(json) {
   List<TimeSeries> dates;
   for (date in json["Weekly Adjusted Time Series"]) {
       dates.add(TimeSeries.fromJson(json, date));
    }
    return dates;
}

Upvotes: 2

Related Questions