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

Flutter对接XAMPP phpMyAdmin提交发票报FormatException异常

问题根因

你碰到的FormatException: Unexpected character (at character 1) <br /> ^异常,本质是后端PHP返回了HTML格式的错误片段——XAMPP默认开启前端错误显示,PHP代码运行报错时会直接输出以<br />开头的HTML错误信息,而Flutter端的响应处理逻辑默认按JSON格式解析返回内容,碰到HTML标签就直接抛出格式错误。
核心触发点就是你排查到的序列化问题:调用json.encode时order_items数组内的订单项被转成了字符串,而非标准JSON对象。出现这个问题只有两种可能:

  1. OrderItem模型没有编写正确的toJson()方法,序列化时直接触发对象的toString(),把结构化数据转成了转义字符串
  2. 组装PurchaseInvoice对象时,你提前对每个OrderItem做了json.encode,把转完的JSON字符串塞进了order_items列表
    后端拿到这种格式的请求时,主发票记录的插入逻辑不依赖order_items字段的解析,所以能正常入库;但循环插入商品行时,代码会把order_items里的元素当数组/对象处理(比如直接写$item['goods_id']取值),此时元素是字符串,PHP直接抛出类型错误,输出HTML报错内容,这也是为什么手动调用接口(手动传参时order_items是标准对象数组)完全正常,只有Flutter端提交会报错。
修复方案
  • 修正模型序列化逻辑
    检查两个模型的toJson()实现,确保OrderItem的toJson()直接返回Map<String, dynamic>结构,不要在任何环节对单个OrderItem提前做json.encode。正确写法参考:
    // 订单项模型正确实现
    class OrderItem {
      final int goodsId;
      final num purchasePrice;
      final int quantity;
    
      OrderItem({required this.goodsId, required this.purchasePrice, required this.quantity});
    
      // 直接返回Map,不要在这层做json.encode
      Map<String, dynamic> toJson() => {
        'goods_id': goodsId,
        'price': purchasePrice,
        'num': quantity,
      };
    }
    
    // 采购发票模型正确实现
    class PurchaseInvoice {
      final String invoiceCode;
      final List<OrderItem> orderItems;
      // 其余发票字段略
    
      PurchaseInvoice({required this.invoiceCode, required this.orderItems});
    
      Map<String, dynamic> toJson() => {
        'invoice_no': invoiceCode,
        // 直接传对象列表,json.encode会自动递归调用每个元素的toJson
        'order_items': orderItems,
      };
    }
    
    必须避免这类错误写法:
    // 错误:提前把单个订单项转成字符串再塞列表
    orderItemList.add(json.encode(currentItem.toJson()));
    
  • 校验序列化结果
    序列化完成后打印请求体,确认order_items内的元素没有被双引号整体包裹、没有多余的转义斜杠,正确结构如下:
    {
      "invoice_no": "CG202405001",
      "order_items": [
        {"goods_id": 1, "price": 12.5, "num": 10},
        {"goods_id": 3, "price": 8.0, "num": 20}
      ]
    }
    
  • 后端增加兜底逻辑(建议配置,避免后续同类问题直接抛HTML错误)
    1. 接口最开头加上header('Content-Type: application/json');,强制所有响应走JSON格式
    2. 解析order_items前增加类型判断,如果元素是字符串类型,先调用json_decode转成数组再处理
    3. 生产环境下修改php.ini配置,设置display_errors = Off,PHP错误直接写入日志,不要向前端输出HTML错误片段
  • 优化Flutter端请求异常捕获
    HTTP请求方法里增加响应格式校验,如果返回内容不是合法JSON,先打印原始响应文本再抛异常,避免因为后端返回非JSON内容时看不到真实报错信息。

改完后重新提交即可正常插入全部数据,不会再触发格式解析异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 04:06:07