Vincit / objection.js

An SQL-friendly ORM for Node.js

Home Page:https://vincit.github.io/objection.js

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ValidationError: field must be object but the schema types is already set into object

fs-arman opened this issue · comments

I have a column augmentedTerms and result both are jsonb in my Postgres.
This augmentedTerms contains an array of strings while
result contains an array of objects.

When I do patch, I got this error:
ValidationError: augmentedTerms: must be object, result: must be object

But the weird thing is that I already set there types into object. (Refer the searchAudit schema below)

Any idea what's wrong? Is this a bug in objection js?
Thanks!

I'm using objection v3.0.1

Expected save data in postgres DB:

id |terms            |results                                              |augmented_terms    |
---+-----------------+-----------------------------------------------------+-------------------+
153|Drafting Services|[799, 62, 659, 660, 678, 685, 686, 703, 718, 722]    |["draft", "servic"]|
154|Engineering      |[116, 669, 2460, 797, 802, 1049, 2382, 118, 767, 880]|["engineer"]       |
/**
 * This is a simple template for bug reproductions. It contains three models `Person`, `Animal` and `Movie`.
 * They create a simple IMDB-style database. Try to add minimal modifications to this file to reproduce
 * your bug.
 *
 * install:
 *    npm install objection knex sqlite3 chai
 *
 * run:
 *    node reproduction-template
 */

  let Model;
  Model = require('objection').Model;

  const Knex = require('knex');

  async function main() {
    await createSchema();

    ///////////////////////////////////////////////////////////////
    // Your reproduction
    ///////////////////////////////////////////////////////////////

    let searchString = 'Honda'
    let terms = ['car', 'transpo']
    let allClassIds = [
      {"id":798,"incClassId":1798,"title":"Engineering Services"},
      {"id":799,"incClassId":2798,"title":"Drafting Services"}
    ]

    let auditEntry = {
      id: 136,
      terms: searchString,
      augmentedTerms: JSON.stringify(terms),
      result: JSON.stringify(allClassIds.map(({ id }) => id))
    }

    console.log('auditEntry:', auditEntry)
    return await searchAudit.query().patch(auditEntry).catch(e => {
      console.log(`Unable to update: ${auditEntry}`)
      console.log(e)
    })
  }

 ///////////////////////////////////////////////////////////////
 // Database
 ///////////////////////////////////////////////////////////////

 const knex = Knex({
   client: 'sqlite3',
   useNullAsDefault: true,
   debug: false,
   connection: {
     filename: ':memory:'
   }
 });

 Model.knex(knex);

 ///////////////////////////////////////////////////////////////
 // Models
 ///////////////////////////////////////////////////////////////

class searchAudit extends Model {
  static get tableName () {
    return 'searchAudit'
  }

  static get jsonSchema () {
    return {
      type: 'object',
      properties: {
        id: { type: 'integer' },
        terms: { type: 'string' },

        augmentedTerms: { type: 'object' },
        result: { type: 'object' }
      }
    }
  }
}
 ///////////////////////////////////////////////////////////////
 // Schema
 ///////////////////////////////////////////////////////////////

 async function createSchema() {
  await knex.schema
    .dropTableIfExists('searchAudit')

   await knex.schema
     .createTable('searchAudit', table => {
       table.increments('id').primary();
       table.string('terms');
       table.jsonb('result');
       table.jsonb('augmentedTerms');
     });
 }

 main()
  .then(() => {
    console.log('success');
    return knex.destroy();
  })
  .catch(err => {
    console.error(err);
    return knex.destroy();
  });

You're stringifying the fields augmentedTerms and result here:

 let auditEntry = {
      id: 136,
      terms: searchString,
      augmentedTerms: JSON.stringify(terms),
      result: JSON.stringify(allClassIds.map(({ id }) => id))
    }

After that, they're strings, not objects. The validation is correct in complaining about it. Remove the calls of JSON.stringify() and you should be all set.