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

Sam*_*ath 29 firebase typescript ionic3 angular google-cloud-firestore

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

错误:使用无效数据调用函数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;
}
Run Code Online (Sandbox Code Playgroud)

码:

  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;
  }
Run Code Online (Sandbox Code Playgroud)

Mat*_*lva 47

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

第一步:

const budgets = arrayOfBudget.map((obj)=> {return Object.assign({}, obj)});
Run Code Online (Sandbox Code Playgroud)

第二步:

const proj: Project = {
      id: data.id,
      name: data.name,
      budgetList: budgets
    }
Run Code Online (Sandbox Code Playgroud)

然后你很高兴去.

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

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

export class User {
        id: string;
        name: string;
    }
Run Code Online (Sandbox Code Playgroud)

并且您尝试执行以下代码:

 const user = new User();   
 this.db.collection('users').doc().set(user)
Run Code Online (Sandbox Code Playgroud)

您将收到如下错误:

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

现在,如果您尝试执行此其他代码行:

 this.db.collection('users').doc().set(Object.assign({}, user))
Run Code Online (Sandbox Code Playgroud)

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

this.db.collection('users').doc().set({id: user.id , name: user.name})
Run Code Online (Sandbox Code Playgroud)

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

UPDATE

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

// Web使用JavaScript对象

下面是文档说明的屏幕截图.

在此输入图像描述

  • 很难分辨,因为我没有看到你的其余代码.但我强烈建议您始终将对象转换为纯JavaScript对象. (4认同)
  • 漂亮,它工作得很好。太感谢了。但你能告诉我为什么有些数组可以工作,有些则不行吗?例如,我在同一个类中有另一个数组,如下所示。但没有错误。有什么解释吗?我也需要像上面所示的那样进行转换吗?`导出类项目 { memberList?: Member[]; }` (2认同)

小智 12

您可以对对象进行字符串化,然后再次解析为对象,以删除该对象的类名称。

const budgets = this.budgetProvider.createBudgets(JSON.parse(JSON.stringify(data.budgetList)), projectId);
Run Code Online (Sandbox Code Playgroud)


And*_*iol 7

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

this.fireStore
  .doc<Project>(`projects/${projectId}/`)
    .set( {...proj} ))
Run Code Online (Sandbox Code Playgroud)

它对我有用

  • 这是迄今为止最简单的,不需要太多努力就可以为我解决问题。 (3认同)
  • { ...proj } 执行浅复制,因此仅当 proj 包含原始类型而不是对其他类型的引用时,此方法才有效。 (2认同)