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

Flutter获取MongoDB聊天室数据时FormatException错误解决

Flutter获取MongoDB聊天室数据触发FormatException问题解决

问题场景

在Flutter项目中调用接口获取MongoDB中的聊天室数据时,触发未处理的FormatException,错误提示:

FormatException: Unexpected character (at character 2)
{_id: 6414a040c01cb2fbea9ede6c, chatTopic: Current Affairs, roomType: publi...
^

相关代码与响应

ChatRoomServices代码

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:onpods/constants/http_error_handelling.dart';
import 'package:onpods/constants/utils.dart';
import 'package:onpods/models/chat_room_model.dart';
import 'package:onpods/models/user_model.dart';
import 'package:http/http.dart' as http;
import 'package:onpods/providers/user_provider.dart';
import 'package:onpods/view/chat_room.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:provider/provider.dart';

import '../../constants/global_constants.dart';

class ChatRoomServices {
  void getChatRoomIndex({
    required BuildContext context,
  }) async {
    http.Response res = await http.get(
      Uri.parse("$uri/get-all-room-index"),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
    );

    print("skjnv");
    print(jsonDecode(res.body)[0]);

    List<ChatRoomModel> allChatRooms = [];

    for (var e in jsonDecode(res.body)) {
      ChatRoomModel temp = ChatRoomModel.fromJson(e.toString());
      allChatRooms.add(temp);
      print(temp.chatTopic);
      print(temp.chatTopic);
    }

    print("skjnv");

    ChatRoom chatRoom;
    // ignore: use_build_context_synchronously
    httpErrorHandle(
      response: res,
      context: context,
      onSuccess: () async {},
    );
  }
}

ChatRoomModel代码

import 'dart:convert';

// ignore_for_file: public_member_api_docs, sort_constructors_first
class ChatRoomModel {
  String chatTopic;
  String roomType;
  Map<String, dynamic> ownerId;
  List<Map<String, dynamic>> speakers;
  List<Map<String, dynamic>> participants;
  String createdAt;
  String updatedAt;
  ChatRoomModel({
    required this.chatTopic,
    required this.roomType,
    required this.ownerId,
    required this.speakers,
    required this.participants,
    required this.createdAt,
    required this.updatedAt,
  });

  Map<String, dynamic> toMap() {
    return <String, dynamic>{
      'chatTopic': chatTopic,
      'roomType': roomType,
      'ownerId': ownerId,
      'speakers': speakers,
      'participants': participants,
      'createdAt': createdAt,
      'updatedAt': updatedAt,
    };
  }

  factory ChatRoomModel.fromMap(Map<String, dynamic> map) {
    return ChatRoomModel(
      chatTopic: map['chatTopic'] as String,
      roomType: map['roomType'] as String,
      ownerId: Map<String, dynamic>.from((map['ownerId'] as Map<String, dynamic>)),
      speakers: List<Map<String, dynamic>>.from(
        (map['speakers'] as List<int>).map<Map<String, dynamic>>(
          (x) => x as Map<String, dynamic>,
        ),
      ),
      participants: List<Map<String, dynamic>>.from(
        (map['participants'] as List<int>).map<Map<String, dynamic>>(
          (x) => x as Map<String, dynamic>,
        ),
      ),
      createdAt: map['createdAt'] as String,
      updatedAt: map['updatedAt'] as String,
    );
  }

  String toJson() => json.encode(toMap());

  factory ChatRoomModel.fromJson(String source) {
    print("Sajs");
    print(source);
    return ChatRoomModel.fromMap(json.decode(source) as Map<String, dynamic>);
  }
}

Postman接口响应(/get-all-room-index)

[
    {
        "_id": "6414a040c01cb2fbea9ede6c",
        "chatTopic": "Current Affairs",
        "roomType": "public",
        "ownerId": {
            "isPublic": true,
            "_id": "6405fe3df459de43b5dadb78",
            "user_name": "Simran Bhalode",
            "user_email": "simran@gmail.com",
            "user_password": "$2b$07$VPHjLNYKicBcEgfyRNT9i.8zok9kU7XqNlNgnpAsZ5V9FN/oyKUka",
            "user_role": "admin",
            "registered_date": "2023-03-06T14:52:45.847Z",
            "__v": 0
        },
        "speakers": [
            {
                "isPublic": true,
                "_id": "6405fe3df459de43b5dadb78",
                "user_name": "Simran Bhalode",
                "user_email": "simran@gmail.com",
                "user_password": "$2b$07$VPHjLNYKicBcEgfyRNT9i.8zok9kU7XqNlNgnpAsZ5V9FN/oyKUka",
                "user_role": "admin",
                "registered_date": "2023-03-06T14:52:45.847Z",
                "__v": 0
            }
        ],
        "participants": [],
        "createdAt": "2023-03-17T17:15:44.873Z",
        "updatedAt": "2023-03-17T17:15:44.873Z",
        "__v": 0
    },
    {
        "_id": "6415e11ddd95481799b016f7",
        "chatTopic": "Current Affairs",
        "roomType": "public",
        "ownerId": {
            "isPublic": true,
            "_id": "6405fe3df459de43b5dadb78",
            "user_name": "Simran Bhalode",
            "user_email": "simran@gmail.com",
            "user_password": "$2b$07$VPHjLNYKicBcEgfyRNT9i.8zok9kU7XqNlNgnpAsZ5V9FN/oyKUka",
            "user_role": "admin",
            "registered_date": "2023-03-06T14:52:45.847Z",
            "__v": 0
        },
        "speakers": [
            {
                "isPublic": true,
                "_id": "6405fe3df459de43b5dadb78",
                "user_name": "Simran Bhalode",
                "user_email": "simran@gmail.com",
                "user_password": "$2b$07$VPHjLNYKicBcEgfyRNT9i.8zok9kU7XqNlNgnpAsZ5V9FN/oyKUka",
                "user_role": "admin",
                "registered_date": "2023-03-06T14:52:45.847Z",
                "__v": 0
            }
        ],
        "participants": [],
        "createdAt": "2023-03-18T16:04:45.928Z",
        "updatedAt": "2023-03-18T16:04:45.928Z",
        "__v": 0
    }
]

错误栈信息

[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: FormatException: Unexpected character (at character 2)
{_id: 6414a040c01cb2fbea9ede6c, chatTopic: Current Affairs, roomType: publi...
 ^
#0      _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1383:5)
#1      _ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:913:48)
#2      _parseJson (dart:convert-patch/convert_patch.dart:35:10)
#3      JsonDecoder.convert (dart:convert/json.dart:610:36)
#4      JsonCodec.decode (dart:convert/json.dart:216:41)
#5      new ChatRoomModel.fromJson
chat_room_model.dart:59
#6      ChatRoomServices.getChatRoomIndex
chat_room_services.dart:33
<asynchronous suspension>

解决方案

核心问题分析

  1. 错误调用fromJson:jsonDecode(res.body)已经将接口响应解析为List<Map<String, dynamic>>,但循环中把每个Map对象转成字符串(e.toString())传给fromJson,而fromJson要求输入合法JSON字符串,但e.toString()生成的是Dart对象的字符串表示(无引号的键名,不符合JSON规范),导致解析失败。
  2. Model类型转换错误:ChatRoomModel.fromMap中把speakers和participants声明为List<int>,但接口返回的是用户对象数组,类型不匹配。

修改步骤

1. 修正ChatRoomServices中的对象转换逻辑

直接使用fromMap解析已解码的Map对象,无需转字符串:

// 替换原循环代码
List<ChatRoomModel> allChatRooms = [];
final decodedData = jsonDecode(res.body) as List<dynamic>;
for (var e in decodedData) {
  ChatRoomModel temp = ChatRoomModel.fromMap(e as Map<String, dynamic>);
  allChatRooms.add(temp);
  print(temp.chatTopic);
}

2. 修正ChatRoomModel中的类型转换

将speakers和participants的List<int>改为List<dynamic>:

// 修改fromMap方法中的对应部分
speakers: List<Map<String, dynamic>>.from(
  (map['speakers'] as List<dynamic>).map<Map<String, dynamic>>(
    (x) => x as Map<String, dynamic>,
  ),
),
participants: List<Map<String, dynamic>>.from(
  (map['participants'] as List<dynamic>).map<Map<String, dynamic>>(
    (x) => x as Map<String, dynamic>,
  ),
),

验证

修改后重新调用接口,即可正常解析聊天室数据,不再触发FormatException。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 22:57:01