【问题标题】:Function DocumentReference.set() called with invalid data. Unsupported field value: a custom Budget object使用无效数据调用的函数 DocumentReference.set()。不支持的字段值:自定义预算对象
【发布时间】:2021-08-20 22:13:00
【问题描述】:

以下代码直到今天都可以正常工作。但我现在不知道它不起作用并给出以下错误。你能告诉我为什么吗?

错误:使用无效数据调用函数 DocumentReference.set()。 不支持的字段值:自定义预算对象

 export class Project {
        id: string = null;
        name: string;
        budgetList?: Budget[];
    }

export class Budget {
    id: string;
    amount: number;
    contingency: number = 20;
    budgetGroup: BudgetGroup = new BudgetGroup();
    creationTime: string;
}

代码:

  async create(data: DtoProject): Promise<Project> {
    try {
      const projectId: string = this.fireStore.createId();
      const budgets = this.budgetProvider.createBudgets(data.budgetList, projectId);//budgets
      const proj: Project = {
        id: data.id,
        name: data.name,
        budgetList: budgets,//here it has the error
      }
      proj.id = projectId;
      await this.fireStore.doc<Project>(`projects/${projectId}/`).set(proj));//project
      }
 }

  createBudgets(data: Budget[], projectId: string): Budget[] {
    let budgets: Budget[] = [];
    forEach(data, (d) => {
      const budgetId: string = this.fireStore.createId();
      d.id = budgetId;
      budgets.push(d);
      this.fireStore.doc<Budget>(`projects/${projectId}/budgets/${budgetId}`).set({
        id: budgetId,
        amount: d.amount,
        contingency: d.contingency,
        budgetGroup: d.budgetGroup,
        creationTime: moment().format()
      })
    })
    return budgets;
  }

【问题讨论】:

  • 我在传入一些字段值意外为空的 json 对象时遇到了这个错误

标签: angular typescript firebase ionic3 google-cloud-firestore


【解决方案1】:

您还可以将 add 方法与新对象一起使用,并使用扩展运算符复制所有值。这对我有用:

const user = new User();   
this.db.collection('users').add({...user});

【讨论】:

    【解决方案2】:

    对我有用

    proj.budgetList = {...budgets}
    
    
    await this.fireStore.doc<Project>(`projects/${projectId}/`).set({...proj}));
    

    【讨论】:

    • 这是JSON.parse(JSON.stringify(budgets)) 的不错替代品(如果字段未定义,则将其添加到对象(这就是区别)并且 fb 会抛出错误 - 这很有用)
    【解决方案3】:

    您还可以使用扩展运算符,例如:

    this.fireStore
      .doc<Project>(`projects/${projectId}/`)
        .set( {...proj} ))
    

    对我有用

    【讨论】:

    • 这是迄今为止最简单的,不需要太多努力就可以为我解决问题。
    • { ...proj } 执行浅拷贝,因此这种方法仅适用于 proj 包含原始类型,而不是对其他类型的引用。
    【解决方案4】:

    错误只是说明输入的数据无效!

    我也遇到了不知从何而来的错误,这是因为我从界面中删除了输入字段,该输入字段应该获取它的值并将其上传到某个集合的文档中!

    注意:检查 .ts 文件 firebase.firestore().collection("some_name").add() / set() 中的代码是否存在一些不必要的字段。

    【讨论】:

      【解决方案5】:

      您必须将预算数组转换为纯 JavaScript 对象数组

      第一步:

      const budgets = arrayOfBudget.map((obj)=> {return Object.assign({}, obj)});
      

      第二步:

      const proj: Project = {
            id: data.id,
            name: data.name,
            budgetList: budgets
          }
      

      那你就可以走了。

      顺便说一句,当使用编译为 JavaScript 的语言进行开发时,您不能使用自定义对象。相反,您必须使用纯 JavaScript 对象来保存在 Firestore 数据库中。

      例如,假设你有下面这个类:

      export class User {
              id: string;
              name: string;
          }
      

      然后你尝试执行以下代码:

       const user = new User();   
       this.db.collection('users').doc().set(user)
      

      你会得到如下错误:

      无效数据。数据必须是对象,但它是:自定义用户对象

      现在,如果您尝试执行另一行代码:

       this.db.collection('users').doc().set(Object.assign({}, user))
      

      您将看到您的对象已保存在数据库中。基本上Object.assign 做同样的事情:

      this.db.collection('users').doc().set({id: user.id , name: user.name})
      

      所以使用Object.assign,它会为你节省很多时间。

      更新

      正如我在下面的评论中指出的那样,您可以找到文档中关于 自定义对象 here 的内容。如您所见,有一个警告说:

      // Web 使用 JavaScript 对象

      下面是文档内容的屏幕截图。

      【讨论】:

      • 美丽,它工作得非常好。太感谢了。但是你能告诉我为什么它可以工作一些数组而有些不能吗?例如我在同一个类中有另一个数组,就像这样。但那里没有错误。有什么解释吗?我是否也需要像上面显示的那样转换它? export class Project { memberList?: Member[]; }
      • 很难说,因为我没有看到你的其余代码。但我强烈建议您始终将对象转换为纯 JavaScript 对象。
      • 不客气。我很高兴能帮助你。 :) 您可以查看文档中有关自定义对象的内容。这是链接:firebase.google.com/docs/firestore/manage-data/add-data 如您所见,有一个警告,如:“Web 使用 JavaScript 对象”。因此使用 Object.assign。
      • 你救了我一天的朋友!完美:)
      • 感谢User 示例和Object.assign
      【解决方案6】:

      您可以将对象字符串化并再次解析为对象以删除对象的类名。

      const budgets = this.budgetProvider.createBudgets(JSON.parse(JSON.stringify(data.budgetList)), projectId);
      

      【讨论】:

      • 我尝试了其他示例,但这对我来说是与 angularfire2 完美配合的示例。
      • 我猜这也可能是修复此错误的方法(在我自己的代码中),它使用的是 JS 类用户{}。这是对我有用的解决方案,但有必要这样做似乎很奇怪。
      猜你喜欢
      • 2019-03-08
      • 2020-06-13
      • 1970-01-01
      • 2019-04-25
      • 2021-01-01
      • 2019-12-07
      • 1970-01-01
      • 2019-12-20
      相关资源
      最近更新 更多