使用 Dart 而不是 Flutter 从 google firebase rest api 解码 json

Decoding json from google firebase rest api using Dart, not Flutter

我可以从 Firebase 中的 Cloud Firestore 实例中的集合中检索文档列表。响应包含我见过的最冗长的 json。这里有一个味道,...

{
  documents: [
    {
      name: projects/myprojectId/databases/(default)/documents/mycollection/0HC2spBFxEMNUc8VQLFg,
      fields: {
        name: {
          stringValue: Jim's Bait Shop},
          taxId: {
            stringValue:
          },
          mailingAddress: {
            mapValue: {
              fields: {
                streetAddress1: {
                  stringValue:
                }
              },
              streetAddress2: {
                stringValue:
              },
              state: {
                stringValue: NC
              },
              city: {
                stringValue: Boone
              },
              zipCode: {
                stringValue:
              }
            }
          }
        }
      },
      createTime: 2020-08-31T19
      :
      54: 28.643464Z,
      updateTime: 2020-09-01T02
      :
      35: 08.203028Z
    },
    {  ...

尝试使用 json解码时,在 dart:convert 中,无法将 json 响应反序列化为 Dart 对象集合。

'_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'

如果我使用 cUrl 而不是 Dart,json 响应看起来同样冗长。

我在“package:firebase/firebase_io.dart”中使用 FirebaseClient 来验证和读取集合。

我试图构建一个“reviver”函数,但 jsonDecode 不接受它,所以我不确定我是怎么搞砸的。

无论如何,我在文档中没有看到太多关于如何将这种冗长的 json 响应编组到 Dart 对象中的指导。我怀疑这个服务器端 Dart 是一个新领域。我想避免需要 Flutter 的包,因为我使用的是预构建的 docker 图像,预装了 Dart 运行时,在 Google Cloud 运行 上。 (老实说,我已经尝试了几个用于 Firestore 的 Flutter 包和一个 Flutter docker 图片。)我会采纳你的任何建议。

下面是我一直用来测试的文件。

import 'package:firebase/firebase_io.dart';
import 'credentials.dart'; // borrowed from a SO post
import 'dart:convert';

const base = 'https://firestore.googleapis.com/v1/projects/';

void main() async {

  // get private key... 
  final credential = await Credentials.fetch(); // string

  final fbClient = FirebaseClient(credential);

  final path = base + 'my_project_id/databases/(default)/documents/my_collection'
  '?mask.fieldPaths=name&mask.fieldPaths=taxId&mask.fieldPaths=mailingAddress&orderBy=orgId';

  final response = await fbClient.get(path);

  print(response);

  final orgs = jsonDecode(response); // unhandled exception

  fbClient.close();
}

我想我可能需要切换到更复杂的 json 反序列化程序包,并注释我的模型 classes 以明确地将这个粗糙的 json 映射到特定的 Dart class 属性。但是我还没有看到支持这种能力的Dart包。

我曾尝试使用“json_serializable: 3.4.1”,但无法生成代码。

在线 json 验证器说由于撇号导致响应格式错误,但我可以相信吗?怀疑我能否转义特殊字符。

解决方案是停止使用 FirebaseClient,因为它没有将 name-value 对括在双引号中。只需使用普通的 http 即可。

import 'package:http/http.dart' as http;

const base = 'https://firestore.googleapis.com/v1/projects/';

void main() async {
  //    
  final uri = base + 'myproject/databases/(default)/documents/mycollection' +
      '?mask.fieldPaths=name&mask.fieldPaths=taxId&mask.fieldPaths=mailingAddress&orderBy=orgId&alt=json';

  var response = await http.get(uri);
  // print(response.body);
  var json = jsonDecode(response.body)['documents'] as List;
  List l = json.map((o) => MyModelClass.fromJson(o)).toList();

https://pub.dev/packages/http

错误消息说 response 不是 String,而是 Map。 这意味着 Firebase 已经为您解析了 JSON 和 returns parsed 结构。

您不需要使用 jsonDecode,只需 final orgs = response;