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

Flutter集成ASP.NET Minimal API时jsonDecode类型不匹配问题解决

Flutter与ASP.NET Minimal API集成的JSON解析错误解决方法

你在Flutter调用ASP.NET Minimal API的MapGet接口时,遇到jsonDecode()报错:

Expected a value of type 'String', but got one of type 'List'

根本原因是API返回的不是标准JSON数组,而是包含半结构化字符串的列表,导致Flutter端无法正确解析。


你的Flutter代码

void main() async {
  final dio = Dio();
  final response = await dio.get('https://localhost:7169/Result');
  print(response.data);
  
  var json = jsonDecode(response.data);

  // Access the JSON values
  String name = json['Drainage_ID'];
  int age = json['date'];

  // Print the values
  print('id: $name');
  print('tarikh: $age');
}

API实际返回格式

[
  "'Drainage_ID': 'DR/C1/IC/H/-/GPG/PU/-/RCP/01','date':'10/5/2022 12:00:00 AM',",
  "'Drainage_ID': 'DR/C1/IC/H/-/GPG/PU/-/RCP/02','date':'10/5/2022 12:00:00 AM',",
  "'Drainage_ID': 'DR/C1/IC/H/-/GPG/SP/-/RCP/01','date':'10/5/2022 12:00:00 AM',",
  ...
]

你的ASP.NET Minimal API代码

app.MapGet("/Result", () =>
{
    var rows = new List<string>();
    using var conn = new SqlConnection(connectionString);
    StringBuilder errorMessages = new StringBuilder();
    conn.Open();
    String query =
        "SELECT TOP 100 A.DR_PI_000_01 AS drainage_id,MAX(A.DR_PI_000_03) AS latest_time " +
        "\r\nFROM DR_PI_000 A\r\n\r\nGROUP BY A.DR_PI_000_01";
    try
    {
        var command = new SqlCommand(query, conn);
        command.CommandTimeout = 1000;
        using SqlDataReader reader = command.ExecuteReader();
        if (reader.HasRows)
        {
            while (reader!.Read())
            {
                rows.Add($"'Drainage_ID': '{(reader.IsDBNull(0) ? null : reader?.GetString(0))}','date':'{(reader!.IsDBNull(1) ? null : reader?.GetDateTime(1))}',");
                
            }
        }
        // …
    }
    catch (SqlException se)
    {
        for (int i = 0; i < se.Errors.Count; i++)
        {
            errorMessages.Append("Index #" + i + "\n" +
                "Message: " + se.Errors[i].Message + "\n" +
                "LineNumber: " + se.Errors[i].LineNumber + "\n" +
                "Source: " + se.Errors[i].Source + "\n" +
                "Procedure: " + se.Errors[i].Procedure + "\n");
        }
        Console.WriteLine(errorMessages.ToString());

    }

    return rows;
})
.WithName("GetResult");

解决方法

方案一:修复ASP.NET API(推荐,标准做法)

问题出在API手动拼接字符串并返回字符串列表,ASP.NET会把它序列化为字符串数组,但每个元素不是合法JSON对象。正确做法是用实体类封装数据,让ASP.NET自动生成标准JSON。

  1. 创建数据实体类
public class DrainageResult
{
    public string Drainage_ID { get; set; }
    public DateTime? Date { get; set; }
}
  1. 修改API逻辑,返回实体列表
app.MapGet("/Result", () =>
{
    var rows = new List<DrainageResult>(); // 改为实体列表
    using var conn = new SqlConnection(connectionString);
    StringBuilder errorMessages = new StringBuilder();
    conn.Open();
    String query =
        "SELECT TOP 100 A.DR_PI_000_01 AS drainage_id,MAX(A.DR_PI_000_03) AS latest_time " +
        "\r\nFROM DR_PI_000 A\r\n\r\nGROUP BY A.DR_PI_000_01";
    try
    {
        var command = new SqlCommand(query, conn);
        command.CommandTimeout = 1000;
        using SqlDataReader reader = command.ExecuteReader();
        if (reader.HasRows)
        {
            while (reader!.Read())
            {
                var result = new DrainageResult
                {
                    Drainage_ID = reader.IsDBNull(0) ? null : reader.GetString(0),
                    Date = reader.IsDBNull(1) ? null : reader.GetDateTime(1)
                };
                rows.Add(result); // 添加实体对象
            }
        }
        // …
    }
    catch (SqlException se)
    {
        // 异常处理逻辑不变
        for (int i = 0; i < se.Errors.Count; i++)
        {
            errorMessages.Append("Index #" + i + "\n" +
                "Message: " + se.Errors[i].Message + "\n" +
                "LineNumber: " + se.Errors[i].LineNumber + "\n" +
                "Source: " + se.Errors[i].Source + "\n" +
                "Procedure: " + se.Errors[i].Procedure + "\n");
        }
        Console.WriteLine(errorMessages.ToString());

    }

    return rows;
})
.WithName("GetResult");

修改后API会返回标准JSON数组:

[
  {
    "Drainage_ID": "DR/C1/IC/H/-/GPG/PU/-/RCP/01",
    "Date": "2022-10-05T00:00:00"
  },
  {
    "Drainage_ID": "DR/C1/IC/H/-/GPG/PU/-/RCP/02",
    "Date": "2022-10-05T00:00:00"
  }
]
  1. 同步修改Flutter代码解析数组
void main() async {
  final dio = Dio();
  final response = await dio.get('https://localhost:7169/Result');
  print(response.data);
  
  // Dio会自动解析JSON,response.data已经是List<Map>,无需手动jsonDecode
  List<dynamic> jsonList = response.data;

  // 循环遍历每个元素
  for (var json in jsonList) {
    String id = json['Drainage_ID'];
    DateTime date = DateTime.parse(json['Date']);
    
    print('id: $id');
    print('tarikh: $date');
  }
}

方案二:Flutter端兼容(不推荐,仅应急)

如果暂时无法修改API,可在Flutter端手动处理非标准格式:

void main() async {
  final dio = Dio();
  final response = await dio.get('https://localhost:7169/Result');
  List<String> stringList = response.data;

  for (var itemStr in stringList) {
    // 清理字符串并包裹成合法JSON对象
    String cleanedStr = "{$itemStr}".replaceAll(',}', '}');
    var json = jsonDecode(cleanedStr);
    
    String id = json['Drainage_ID'];
    DateTime date = DateTime.parse(json['date']);
    
    print('id: $id');
    print('tarikh: $date');
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:35:32