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

时间:2018-01-08 18:39:56

标签: angular typescript firebase ionic3 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;
}

代码:

  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;
  }

6 个答案:

答案 0 :(得分:35)

您必须将您的预算数组转换为纯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对象

下面是文档说明的截图。

enter image description here

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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

我也从无处面临错误,这是因为我从接口中删除了应该获取其值并将其上传到某个集合的文档中的输入字段!

注意:如果没有不必要的字段,请检查.ts文件var settings = new JsonSerializerSettings { ContractResolver = resolver, }; string json = JsonConvert.SerializeObject(obj, settings); 中的代码。

答案 4 :(得分:0)

您还可以使用传播运算符,例如:

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

对我有用

答案 5 :(得分:-1)

对我有用

proj.budgetList = {...budgets}


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