0
votes

How to add/map multiple json objects to dart object

import 'dart:async';
import 'dart:convert';

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

Future<List<Photo>> fetchPhotos(http.Client client) async {
  final response =
  await client.get('https://cloud.iexapis.com/stable/stock/market/batch?symbols=SLVO,MONY&types=stats&token=');
  /*String response = '''
 {"AAPL":
   {"stats":{"week52change":0.232986,"week52high":255.93,"week52low":142,"marketcap":1136677331400,"employees":137000,"day200MovingAvg":199.29,"day50MovingAvg":225.28,"float":4436680630.59,"avg10Volume":26482506.4,"avg30Volume":26817874.5,"ttmEPS":11.9342,"ttmDividendRate":3,"companyName":"Apple, Inc."
   }
   },
 "FB":
   {"stats":{"week52change":0.1,"week52high":255.93,"week52low":142,"marketcap":1136677331400,"employees":137000,"day200MovingAvg":199.29,"day50MovingAvg":225.28,"float":4436680630.59,"avg10Volume":26482506.4,"avg30Volume":26817874.5,"ttmEPS":11.9342,"ttmDividendRate":3,"companyName":"Apple, Inc."
   }
   }
}
  ''';*/
  // Use the compute function to run parsePhotos in a separate isolate.
  return compute(parsePhotos, response.body);
}

// A function that converts a response body into a List<Photo>.
List<Photo> parsePhotos(String responseBody) {
 //final parsed = json.decode(responseBody).cast<Map<String,dynamic>>();

  //return parsed.map<Photo>((json) => Photo.fromJson(json)).toList();

  dynamic Obj = json.decode(responseBody);
  print(Obj.length);
  List<Photo> photoList = [];
  Obj.forEach((k, v,z) => photoList.add(Photo(k,v,z)));

  return photoList;
}

class Photo {
  String symbol;
   String companyName;
  dynamic stats;
  //dynamic stats;
  Photo(this.symbol ,this.stats,this.companyName);
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final appTitle = 'Isolate Demo';

    return MaterialApp(
      title: appTitle,
      home: MyHomePage(title: appTitle),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: FutureBuilder<List<Photo>>(
        future: fetchPhotos(http.Client()),
        builder: (context, snapshot) {
          if (snapshot.hasError) print(snapshot.error);

          return snapshot.hasData
              ? PhotosList(photos: snapshot.data)
              : Center(child: CircularProgressIndicator());
        },
      ),
    );
  }
}

class PhotosList extends StatelessWidget {
  final List<Photo> photos;

  PhotosList({Key key, this.photos}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GridView.builder(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
      ),
      itemCount: photos.length,
      itemBuilder: (context, index) {
        return ListTile(
          leading: Icon(Icons.album),
           title: Column(  children: [
             Text(photos[index].symbol),
                      Text(photos[index].companyName),
                   ],
                   ),
          subtitle: Column(
            children: [
             // Text( ' ${photos[index].stats["stats"]["dividendYield"]["companyName"]}'),
            //  Text( ' ${photos[index].data["quote"]["iexRealtimePrice"]}' ' ${photos[index].stats["stats"]["dividendYield"]["companyName"]}'),
             // Text( ' ${photos[index].data["quote"]["iexRealtimePrice"]}'),
            Text ( '${photos[index].stats["dividendYield"] ?? ""}'),
            ],
          ),
         //title: Text(photos[index].symbol),
         //subtitle: Text( ' ${photos[index].stats["stats"]["dividendYield"]["companyName"]}'),
          //subtitle: Text( ' ${photos[index].data["quote"]["iexRealtimePrice"]}' ' ${photos[index].stats["stats"]["dividendYield"]["companyName"]}'),
       // subtitle: Text( ' ${photos[index].data["quote"]["iexRealtimePrice"]}'),
         // subtitle: Text ( ' ${photos[index].stats["stats"]["dividendYield"]}'),
        );
      },
    );
  }
}

Json

{"SLVO":{"stats":{"week52change":0.047256,"week52high":7.48,"week52low":6.23,"marketcap":null,"employees":null,"day200MovingAvg":6.88,"day50MovingAvg":7.13,"float":null,"avg10Volume":7454.8,"avg30Volume":7927.83,"ttmEPS":null,"ttmDividendRate":null,"companyName":"Credit Suisse X-Links Silver Shares Covered Call ETN","sharesOutstanding":0,"maxChangePercent":58.7391,"year5ChangePercent":-0.4128,"year2ChangePercent":-0.1369,"year1ChangePercent":0.047256,"ytdChangePercent":-0.005789,"month6ChangePercent":0.074445,"month3ChangePercent":-0.035112,"month1ChangePercent":-0.025532,"day30ChangePercent":-0.035112,"day5ChangePercent":-0.007225,"nextDividendDate":null,"dividendYield":null,"nextEarningsDate":null,"exDividendDate":null,"peRatio":null,"beta":-0.06347545711182472},"quote":{"symbol":"SLVO","companyName":"Credit Suisse X-Links Silver Shares Covered Call ETN","primaryExchange":"NASDAQ","calculationPrice":"close","open":6.89,"openTime":1574346600589,"close":6.88,"closeTime":1574370000242,"high":6.9,"low":6.87,"latestPrice":6.88,"latestSource":"Close","latestTime":"November 21,

Added: &types=stats,quote&token

enter image description here

Example

error

I/flutter (28411): Exception: type '(dynamic, dynamic, dynamic) => void' is not a subtype of type '(String, dynamic) => void' of 'f' I/flutter (28411): 71 I/flutter (28411): Exception: type '(dynamic, dynamic, dynamic) => void' is not a subtype of type '(String, dynamic) => void' of 'f'

1
could you provide token to allow me to check? - chunhunghan

1 Answers

1
votes

I have modified url to contains stats and quote
You can not use two dynamic, its for map
and you still need dynamic field name
You can add token and run with full code, demo picture is as below
code snippet

 Text ( '${photos[index].data["stats"]["dividendYield"] ?? ""}'),
 Text ( '${photos[index].data["stats"]["week52change"] ?? ""}'),
 Text ( '${photos[index].data["quote"]["companyName"] ?? ""}'),

demo

enter image description here

full code

import 'dart:async';
import 'dart:convert';

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

Future<List<Photo>> fetchPhotos(http.Client client) async {
  final response =
  await client.get('https://cloud.iexapis.com/stable/stock/market/batch?symbols=SLVO,MONY&types=stats,quote&token=');

  // Use the compute function to run parsePhotos in a separate isolate.
  return compute(parsePhotos, response.body);
}

// A function that converts a response body into a List<Photo>.
List<Photo> parsePhotos(String responseBody) {
  //final parsed = json.decode(responseBody).cast<Map<String,dynamic>>();

  //return parsed.map<Photo>((json) => Photo.fromJson(json)).toList();

  dynamic Obj = json.decode(responseBody);
  print(responseBody);
  print(Obj.length);

  List<Photo> photoList = [];
  Obj.forEach((k, v) => photoList.add(Photo(k,v)));

  return photoList;
}

class Photo {
  String symbol;
  //String companyName;
  dynamic data;
  //dynamic quote;
  Photo(this.symbol ,this.data);
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final appTitle = 'Isolate Demo';

    return MaterialApp(
      title: appTitle,
      home: MyHomePage(title: appTitle),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: FutureBuilder<List<Photo>>(
        future: fetchPhotos(http.Client()),
        builder: (context, snapshot) {
          if (snapshot.hasError) print(snapshot.error);

          return snapshot.hasData
              ? PhotosList(photos: snapshot.data)
              : Center(child: CircularProgressIndicator());
        },
      ),
    );
  }
}

class PhotosList extends StatelessWidget {
  final List<Photo> photos;

  PhotosList({Key key, this.photos}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GridView.builder(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
      ),
      itemCount: photos.length,
      itemBuilder: (context, index) {
        return ListTile(
          leading: Icon(Icons.album),
          title: Column(  children: [
            Text(photos[index].symbol),
            //Text(photos[index].companyName),
          ],
          ),
          subtitle: Column(
            children: [
              // Text( ' ${photos[index].stats["stats"]["dividendYield"]["companyName"]}'),
              //  Text( ' ${photos[index].data["quote"]["iexRealtimePrice"]}' ' ${photos[index].stats["stats"]["dividendYield"]["companyName"]}'),
              // Text( ' ${photos[index].data["quote"]["iexRealtimePrice"]}'),
              Text ( '${photos[index].data["stats"]["dividendYield"] ?? ""}'),
              Text ( '${photos[index].data["stats"]["week52change"] ?? ""}'),
              Text ( '${photos[index].data["quote"]["companyName"] ?? ""}'),
            ],
          ),
          //title: Text(photos[index].symbol),
          //subtitle: Text( ' ${photos[index].stats["stats"]["dividendYield"]["companyName"]}'),
          //subtitle: Text( ' ${photos[index].data["quote"]["iexRealtimePrice"]}' ' ${photos[index].stats["stats"]["dividendYield"]["companyName"]}'),
          // subtitle: Text( ' ${photos[index].data["quote"]["iexRealtimePrice"]}'),
          // subtitle: Text ( ' ${photos[index].stats["stats"]["dividendYield"]}'),
        );
      },
    );
  }
}