Функция DocumentReference.set() вызывается с недопустимыми данными. Неподдерживаемое значение поля: пользовательский объект бюджета

Ниже код работает отлично до сегодняшнего дня. Но я не знаю, теперь он не работает и дает ошибку ниже. Не могли бы вы рассказать мне, почему?

Ошибка: функция 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;
  }

Ответ 1

Вы должны преобразовать свой массив бюджетов в массив чистых объектов 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)

Вы получите ошибку вроде:

неверные данные. Данные должны быть объектом, но это был: пользовательский объект 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, это сэкономит вам много времени.

ОБНОВИТЬ

Как я указал в комментарии ниже, вы можете найти то, что документация говорит о пользовательских объектах здесь. Как видите, есть предупреждение:

//Веб использует объекты JavaScript

Ниже приведен скриншот того, что написано в документации.

enter image description here

Ответ 2

Вы можете преобразовать объект в строку и снова проанализировать его, чтобы удалить имена классов объекта.

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

Ответ 3

Ошибка просто говорит о том, что введенные данные неверны!

Я также столкнулся с ошибкой из ниоткуда, потому что я удалил поле ввода из интерфейса, который должен был получить его значение и загрузить его в документ некоторой коллекции!

примечание: проверьте ваш код в .ts файле firebase.firestore firebase.firestore().collection("some_name").add()/set() если есть какое-то ненужное поле или нет.

Ответ 4

Вы также можете использовать оператор распространения как:

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

Это работает для меня