You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter 如何将接口返回的JSON国家数据填充为DropdownMenuItem选项

问题核心原因梳理

你遇到的问题主要由3个不匹配导致:

  • 数据模型和实际接口返回的外层字段不匹配:你定义的GetCountry类读取外层isSuccess字段,但是实际接口返回的外层成功状态字段是status
  • 数据模型和实际接口返回的内层字段不匹配:你定义的CountryModal类读取countryName、int类型id,但实际接口返回的名称字段是stateName、id是字符串类型
  • 没有将接口拉取到的结果赋值给下拉菜单的数据源_countrylist,导致下拉菜单的items始终为空

修复步骤

1. 修正数据模型,对齐实际接口返回

import 'dart:convert';

GetCountry getCountryFromJson(String str) => GetCountry.fromJson(json.decode(str));

String getCountryToJson(GetCountry data) => json.encode(data.toJson());

class GetCountry {
  GetCountry({
    required this.data,
    this.exceptionInfo,
    this.message,
    this.messages,
    required this.isSuccess,
  });

  List<CountryModal> data;
  dynamic exceptionInfo;
  dynamic message;
  dynamic messages;
  bool isSuccess;

  factory GetCountry.fromJson(Map<String, dynamic> json) => GetCountry(
    // 对齐实际接口的成功状态字段
    isSuccess: json["status"] ?? false,
    data: List<CountryModal>.from(json["data"].map((x) => CountryModal.fromJson(x))),
    exceptionInfo: json["exceptionInfo"],
    message: json["message"],
    messages: json["messages"],
  );

  Map<String, dynamic> toJson() => {
    "data": List<dynamic>.from(data.map((x) => x.toJson())),
    "exceptionInfo": exceptionInfo,
    "message": message,
    "messages": messages,
    "isSuccess": isSuccess,
  };
}

class CountryModal {
  CountryModal({
    required this.id,
    required this.countryName,
  });

  // 对齐实际接口的id类型(字符串)
  String id;
  // 如果你实际调用的是获取国家的接口,这里保留countryName即可;如果是返回stateName的接口,就把字段名改成stateName
  String countryName;

  factory CountryModal.fromJson(Map<String, dynamic> json) => CountryModal(
    id: json["id"],
    // 对应上面的字段名调整读取的key
    countryName: json["countryName"] ?? json["stateName"] ?? "",
  );

  Map<String, dynamic> toJson() => {
    "id": id,
    "countryName": countryName,
  };
}

2. 页面中调用接口赋值给下拉数据源

在你的StatefulWidget的initState生命周期中调用接口,拉取数据后赋值给_countrylist并刷新页面:

List<CountryModal> _countrylist = [];
// 修改为可空类型,适配未选择的空状态
String? mycountry;

@override
void initState() {
  super.initState();
  loadCountryData();
}

Future<void> loadCountryData() async {
  // 替换为你实际的授权token
  String authToken = "你的接口授权token";
  try {
    GetCountry res = await Getcountry(authToken);
    if(res.isSuccess){
      setState(() {
        _countrylist = res.data;
      });
    }
  } catch (e) {
    print("国家数据加载失败:$e");
  }
}

3. 修正下拉菜单代码,适配空安全

DropdownButton<String>(
  // 明确指定value的类型为String,避免类型不匹配报错
  items: _countrylist.map((item) {
    return DropdownMenuItem<String>(
      child: Text(
        item.countryName,
        style: const TextStyle(fontSize: 14.0),
      ),
      // 现在id已经是字符串类型,不需要再调用toString
      value: item.id,
    );
  }).toList(),
  hint: const Text(
    "Please select the country",
    style: TextStyle(
      color: Colors.black45,
    ),),
  onChanged: (newVal) {
    setState(() {
      mycountry = newVal;
    });
  },
  value: mycountry,
)

内容的提问来源于stack exchange,提问作者palak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 05:00:03