如何向Firebase Firestore添加嵌套数组?解决不支持报错问题
Firestore嵌套数组存储解决方案
问题背景
尝试向Firebase Firestore存储嵌套数组时触发错误:
Unhandled Exception: [cloud_firestore/unknown] Invalid data. Nested arrays are not supported
拟存储的JSON数据:
{ "time": "7:00pm", "isSet": false, "leds": [ [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0] ] }
对应的Dart Model类:
class LampModes { String name; int index; List<List<int>> leds; LampModes(this.name, this.index, this.leds); }
可行解决方案
Firestore不支持直接存储嵌套数组,但可以通过以下三种方式绕过限制:
1. 将子数组包装为对象
把每个子数组封装成带字段的对象,让Firestore识别为对象数组而非嵌套数组。
修改后的Model类:
class LampModes { String name; int index; List<LedRow> leds; LampModes(this.name, this.index, this.leds); // 转换为Firestore可存储的Map结构 Map<String, dynamic> toMap() { return { 'name': name, 'index': index, 'leds': leds.map((row) => row.toMap()).toList(), }; } } class LedRow { List<int> values; LedRow(this.values); Map<String, dynamic> toMap() { return {'values': values}; } }
存储后的Firestore数据结构:
{ "name": "示例模式", "index": 0, "leds": [ {"values": [0,0,0,0]}, {"values": [0,0,0,0]}, // ... 其余行数据 ] }
2. 扁平化二维数组
如果子数组长度固定(如示例中每行4个元素),可将二维数组转为一维数组,同时记录行长度用于后续还原。
修改后的Model类:
class LampModes { String name; int index; List<int> flatLeds; final int rowLength = 4; // 固定子数组长度 // 构造时自动扁平化二维数组 LampModes(this.name, this.index, List<List<int>> leds) : flatLeds = leds.expand((row) => row).toList(); // 从扁平化数组还原二维数组 List<List<int>> get leds { List<List<int>> result = []; for (int i = 0; i < flatLeds.length; i += rowLength) { result.add(flatLeds.sublist(i, i + rowLength)); } return result; } // 转换为Firestore可存储的Map结构 Map<String, dynamic> toMap() { return { 'name': name, 'index': index, 'flatLeds': flatLeds, 'rowLength': rowLength, }; } }
存储后的Firestore数据结构:
{ "name": "示例模式", "index": 0, "flatLeds": [0,0,0,0,0,0,0,0,...], // 所有子数组元素依次排列 "rowLength": 4 }
3. 序列化为JSON字符串
将二维数组序列化为JSON字符串存储,读取时再反序列化还原,适合无需在Firestore中查询数组内容的场景。
修改后的Model类:
import 'dart:convert'; class LampModes { String name; int index; List<List<int>> leds; LampModes(this.name, this.index, this.leds); // 转换为Firestore可存储的Map结构 Map<String, dynamic> toMap() { return { 'name': name, 'index': index, 'ledsJson': jsonEncode(leds), }; } // 从Firestore读取的Map还原对象 factory LampModes.fromMap(Map<String, dynamic> map) { return LampModes( map['name'], map['index'], (jsonDecode(map['ledsJson']) as List).map((item) => (item as List).cast<int>()).toList(), ); } }
存储后的Firestore数据会包含一个ledsJson字段,值为二维数组的JSON序列化字符串。
内容的提问来源于stack exchange,提问作者Nikunj Ramani
相关产品推荐
相关产品推荐

