如何将本地JSON加载到List<Map>变量中?

4

我该如何将本地json加载到List<Map>变量中?

这是我的本地json。

[
  {“id”: 00”, “name”: ”TRL”},
  {“id”: 01”, “name”: ”USD”},
  {“id”: 02”, “name”: ”GBP”},
  {“id”: 03”, “name”: ”EUR”},
]

然而这是如何工作的:

List<Map> _myCurrency = [
  {“id”: 00”, “name”: ”TRL”},
  {“id”: 01”, “name”: ”USD”},
  {“id”: 02”, “name”: ”GBP”},
  {“id”: 03”, “name”: ”EUR”},
];

我的问题是我将货币数据移动到currency.json文件中。我可以加载json,但无法分配给List< Map >变量。请帮忙解决一下? 更新:
String jsonTCBanks =
await rootBundle.loadString("packages/capi/currency.json");
List<Map> _myCurrency = json.decode(jsonTCBanks);

我收到以下错误信息:

type 'List<dynamic>' is not a subtype of type 'List<Map<dynamic, dynamic>>'
如果我使用Map _myCurrency,则json.decode可以工作,但是我会失去键值属性。
更新-2: 我一直收到以下错误:
I/flutter (16273): The following assertion was thrown building MyHomePage(dirty, state: _MyHomePageState#44865):
I/flutter (16273): type 'MappedListIterable<Map<dynamic, dynamic>, DropdownMenuItem<dynamic>>' is not a subtype of type
I/flutter (16273): 'List<DropdownMenuItem<String>>'

    class _MyHomePageState extends State<MyHomePage> {
      String _mySelectedCurrency;
      List<Map> _myCurrencies;

      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        _loadLocalJsonData();
      }

      Future _loadLocalJsonData() async {
        String jsonCurrency = await rootBundle
            .loadString("packages/capi/currency.json");
        setState(() {
          _myCurrencies = List<Map>.from(jsonDecode(jsonCurrency) as List);
          print("*******_myCurrencies: $_myCurrencies");// This part works correctly
        }); 
      }

      @override
      Widget build(BuildContext context) {
        return _myCurrencies == null ? _buildWait(context) : _buildRun(context);
      }

  // TODO: BUILD RUN
  Widget _buildRun(BuildContext context) {
    final _itemsName = _myCurrencies.map((c) {
      return new DropdownMenuItem<String>(
        value: c["id"].toString(),
        child: new Text(c["name"].toString()),
      );
    }).toList();

    return new Scaffold(
        key: _scaffoldKey,
        body: new SafeArea(
            top: false,
            bottom: false,
            child: new Form(
                key: _formKey,
                child: new ListView(
                  padding: const EdgeInsets.symmetric(
                      horizontal: 16.0, vertical: 32.0),
                  children: <Widget>[
                    //TODO: CURRENCY ###########################################
                    new FormField<String>(
                      builder: (FormFieldState<String> state) {
                        return InputDecorator(
                          decoration: InputDecoration(
                            labelText: 'CHOOSE CURRENCY',
                            labelStyle: TextStyle(
                                fontSize: 18.0,
                                fontWeight: FontWeight.bold,
                                color: Colors.green.shade700),
                            errorText: state.hasError ? state.errorText : null,
                          ),
                          isEmpty: _mySelectedCurrency == '',
                          child: new DropdownButtonHideUnderline(
                            child: new DropdownButton<String>(
                              style: TextStyle(
                                fontSize: 14.0,
                                color: Colors.black,
                                fontWeight: FontWeight.w500,
                              ),
                              value: _mySelectedCurrency,
                              isDense: true,
                              onChanged: (String newValue) {
                                setState(() {
                                  _mySelectedCurrency = newValue;
                                  state.didChange(newValue);
                                });
                              },
                              items: _itemsName,
                            ),
                          ),
                        );
                      },
                      validator: (val) {
                        return val != '' ? null : 'Choose Currency...';
                      },
                    ),
                  ],
                ))));
  }

      // TODO: BUILD WAIT
      Widget _buildWait(BuildContext context) {
        return new Scaffold(
          body: new Center(child: CircularProgressIndicator()),
        );
      }

    }
1个回答

2
你需要将字符串解码为数据结构并通过创建一个新列表来调整类型,其中你将传递从 jsonDecode 返回的列表。
import 'dart:convert';

...

List<Map> _myCurrency = List<Map>.from(jsonDecode(json) as List);

final currencyItems = _myCurrency.map(
    (c) => DropdownMenuItem<String>(c['id'], child: Text(c['name'])).toList();
DropdownButton(items: currencyItems);     

我更新了我的问题。我收到了错误信息:类型“List<dynamic>”不是类型“List<Map<dynamic, dynamic>>”的子类型。 - Nick
我会尝试,谢谢。如果不行的话,我会开个新的问题。 - Nick
你需要检查 _myCurrencies 是否为 null。 Futures 不会立即完成(这正是它们的目的),只有当 Future 完成时,_myCurrencies 才会有值。当 _myCurrenciesnull 时调用 build(),你需要做一些其他的事情(返回一个空的 Container(),或者创建一个没有任何条目的下拉菜单,...)。此外,你需要调用 setState,以便在 Future 完成时再次执行 build(),如下所示:setState(() =>_myCurrencies = List<Map>.from(jsonDecode(jsonCurrency) as List)); - Günter Zöchbauer
谢谢,我更新了我的代码。这次我遇到了这个错误:类型“MappedListIterable<Map<dynamic, dynamic>, DropdownMenuItem<String>>”不是类型“List<DropdownMenuItem<String>>”的子类型。要么断言指示框架本身存在错误,要么我们应该在此错误消息中提供更多信息,以帮助您确定和修复根本原因。 - Nick
在发布版本中,溢出不会像调试版本那样可见,但修复此问题仍然是个好主意。但是为此你应该创建一个新的问题。 - Günter Zöchbauer
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接