【问题标题】:How to convert a Firestore Document to plain json and vice versa如何将 Firestore 文档转换为纯 json,反之亦然
【发布时间】:2020-06-07 13:57:42
【问题描述】:

我正在尝试使用 Rest API 获取 Firestore 文档,它以以下格式返回数据

{"fields":{"list1":{"arrayValue":{"values":[{"stringValue":"item1"},{"stringValue":"item2"}]}}}}

如何在进行更新调用之前将上述文档转换为纯 JavaScript 对象,然后将其转换回 Firestore 文档

{"list1":["item1","item2"]}

Firestore 控制台中我的数据的屏幕截图

编辑:更多信息

json sample1 由 Firestore api 返回并包含所有数据类型信息

json sample2 是我的实际数据,没有类型信息。

我的问题是 firestore RestApi get 调用以 json sample1 格式返回响应。我想更新 api 响应中的一些信息并将更新的值发送回 firestore db。但是由于响应中的所有类型信息,我无法在必要时更新值。所以我正在尝试寻找是否有办法将 api 响应转换为 json sample2。

使用的 API 网址:https://firestore.googleapis.com/v1/projects/projects/{project_id}/databases/{database_id}/documents/{document_path}

【问题讨论】:

  • 我不明白你想做什么,问题是什么。据我所知,您显示的两个 sn-ps 都是有效的 JSON。您能否编辑您的问题以显示您编写的代码、遇到的错误或卡在哪里?
  • @FrankvanPuffelen 更新了问题并提供了更多信息

标签: javascript firebase google-cloud-firestore


【解决方案1】:

似乎使用 rest api 的唯一方法是编写自己的转换。下面的代码符合我的要求

let jsonToDocument = function (value) {
    if (!isNaN(value)) {
        if (value.toString().indexOf('.') != -1)
            return { 'doubleValue': value };
        else
            return { 'integerValue': value };
    } else if (value === 'true' || value === 'false' || typeof value == 'boolean') {
        return { 'booleanValue': value };
    } else if (Date.parse(value)) {
        return { 'timestampValue': value };
    } else if (typeof value == 'string') {
        return { 'stringValue': value };
    } else if (value && value.constructor === Array) {
        return { 'arrayValue': { values: value.map(v => jsonToDocument(v)) } };
    } else if (typeof value === 'object') {
        let obj = {};
        for (let o in value) {
            obj[o] = jsonToDocument(value[o]);
        }
        return { 'mapValue': { fields: obj } };
    }

}
let documentToJson = function (fields) {
    let result = {};
    for (let f in fields) {
        let key = f, value = fields[f],
            isDocumentType = ['stringValue', 'booleanValue', 'doubleValue',
                'integerValue', 'timestampValue', 'mapValue', 'arrayValue'].find(t => t === key);
        if (isDocumentType) {
            let item = ['stringValue', 'booleanValue', 'doubleValue', 'integerValue', 'timestampValue']
                .find(t => t === key)
            if (item)
                return value;
            else if ('mapValue' == key)
                return documentToJson(value.fields || {});
            else if ('arrayValue' == key) {
                let list = value.values;
                return !!list ? list.map(l => documentToJson(l)) : [];
            }
        } else {
            result[key] = documentToJson(value)
        }
    }
    return result;
}
let documentData = { "list1": { "arrayValue": { "values": [{ "stringValue": "item1" }, { "stringValue": "item2" }] } } }
let jsonData = documentToJson(documentData);
let documentData1 = jsonToDocument(jsonData).mapValue.fields;
console.log(JSON.stringify(documentData));
console.log(JSON.stringify(jsonData));
console.log(JSON.stringify(documentData1));

【讨论】:

  • 很棒的 sn-p,特别感谢您发布两种转换方式。帮了我很多!
【解决方案2】:

我只是想建议对@mahindar 处理“nullValue”的答案稍作改动,因为 Firestore 最近允许保存空值。以下是更新后的代码

let jsonToDocument = function (value) {
    if (!value) {
        return { 'nullValue': null };
    } else if (!isNaN(value)) {
        if (value.toString().indexOf('.') != -1)
            return { 'doubleValue': value };
        else
            return { 'integerValue': value };
    } else if (value === 'true' || value === 'false' || typeof value == 'boolean') {
        return { 'booleanValue': value };
    } else if (Date.parse(value)) {
        return { 'timestampValue': value };
    } else if (typeof value == 'string') {
        return { 'stringValue': value };
    } else if (value && value.constructor === Array) {
        return { 'arrayValue': { values: value.map(v => jsonToDocument(v)) } };
    } else if (typeof value === 'object') {
        let obj = {};
        for (let o in value) {
            obj[o] = jsonToDocument(value[o]);
        }
        return { 'mapValue': { fields: obj } };
    }

}
let documentToJson = function (fields) {
    let result = {};
    for (let f in fields) {
        let key = f, value = fields[f],
            isDocumentType = ['stringValue', 'booleanValue', 'doubleValue',
                'integerValue', 'timestampValue', 'mapValue', 'arrayValue', 'nullValue'].find(t => t === key);
        if (isDocumentType) {
            let item = ['stringValue', 'booleanValue', 'doubleValue', 'integerValue', 'timestampValue', 'nullValue']
                .find(t => t === key)
            if (item)
                return value;
            else if ('mapValue' == key)
                return documentToJson(value.fields || {});
            else if ('arrayValue' == key) {
                let list = value.values;
                return !!list ? list.map(l => documentToJson(l)) : [];
            }
        } else {
            result[key] = documentToJson(value)
        }
    }
    return result;
}
let documentData = { "list1": { "arrayValue": { "values": [{ "stringValue": "item1" }, { "stringValue": "item2" }] } }, "another_value": { "nullValue": null } }
let jsonData = documentToJson(documentData);
let documentData1 = jsonToDocument(jsonData).mapValue.fields;
console.log(JSON.stringify(documentData));
console.log(JSON.stringify(jsonData));
console.log(JSON.stringify(documentData1));

【讨论】:

  • !value 匹配所有计算结果为 false 的内容,包括空字符串、布尔值 false 等等。通过value === null检查会更好。
【解决方案3】:

要转换这个输入:

{"fields":{"list1":{"arrayValue":{"values":[{"stringValue":"item1"},{"stringValue":"item2"}]}}}}

到这个输出:

{"list1":["item1","item2"]}

你可以这样做:

let input = {"fields":{"list1":{"arrayValue":{"values":[{"stringValue":"item1"},{"stringValue":"item2"}]}}}};

let expected = {"list1":["item1","item2"]};

let output = {};
Object.keys(input.fields).forEach((fieldName) => {
  let arrayValue = input.fields[fieldName].arrayValue;
  if (arrayValue) {
    output[fieldName] = arrayValue.values.map((value) => value.stringValue);
  }
});

console.log(output);

【讨论】:

  • 这是唯一的方法吗?因为我共享的 Json 是示例之一,真实文档可能具有不同的结构,包括数字、字符串、数组、日期和嵌套对象、数组。我不知道firestore api是否已经具备在api端本身进行这种解析的能力
  • search of the Firestore JavaScript SDK 看来,他们正在做类似的事情。除非您使用 Firestore JavaScript SDK,否则您必须自己编写或开始使用为您执行此操作的库。但到那时,为什么不使用 Firebase JavaScript SDK 开始呢?
猜你喜欢
  • 2012-03-24
  • 1970-01-01
  • 2011-05-10
  • 1970-01-01
  • 2013-08-09
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
相关资源
最近更新 更多