objection.js icon indicating copy to clipboard operation
objection.js copied to clipboard

patch validator fails on JSON column updates when jsonSchema contains additionalProperties:false

Open bompus opened this issue 5 years ago • 2 comments

static get jsonSchema() {
    return {
      type: 'object',
      additionalProperties: false,
      properties: {
        id: { type: 'integer' },
        meta: {
          type: 'object',
          additionalProperties: false,
          properties: {
            a: { type: 'string' },
            b: { type: 'string' }
          }
        }
      }
    };
  }

Trying to .patch({ "meta:b": "foo" }) results in the error "ValidationError: meta:b: is an invalid additional property"

I monkey-patched modelSet.js setJson function to iterate over the references and turn that into: { meta: { b: "foo" } } to get it to work, but I wasn't certain if that was the proper location to make that change, so I didn't submit a PR yet.

My code is below for how I was able to resolve it temporarily locally:

-- modelSet.js
function setJson(model, json, options) {
...
  // BEGIN: ADDED
  const { ref } = require('../queryBuilder/ReferenceBuilder');

  for (const key of Object.keys(json)) {
    let val = json[key];

    if (key.indexOf(':') > -1) {
      // 'jsonColumn:attr' : 123 is transformed to { jsonColumn: { attr: 123 } }
      let parsed = ref(key);
      let jsonRef = parsed.parsedExpr.access[0].ref;

      if (json[parsed.column] === undefined) {
        json[parsed.column] = {};
      }

      json[parsed.column][jsonRef] = val;
      delete json[key];
    }
  }
  // END: ADDED

  json = model.$parseJson(json, options);
...

Thoughts?

bompus avatar Jan 28 '20 06:01 bompus

I've always cosidered using additionalProperties: false pretty useless with model classes. I've always preferred using removeAdditional instead.

koskimas avatar Jan 28 '20 08:01 koskimas

Thanks for the tip. I was able to get it working by specifying options.removeAdditional:true in createValidator.

However, I'd rather receive a validation error (especially for JSON database columns) rather than have the extra keys removed and not end up in the database.

Until this is resolved, to achieve the desired behavior, It looks like I'm going to have to .fetch() -> merge objects -> use .update() instead of simply .patch() for my Models containing JSON columns. Not a big deal, I was just trying to reduce queries by using patch here.

bompus avatar Jan 28 '20 20:01 bompus