ajv-validator / ajv

The fastest JSON schema Validator. Supports JSON Schema draft-04/06/07/2019-09/2020-12 and JSON Type Definition (RFC8927)
https://ajv.js.org
MIT License
13.8k stars 875 forks source link

Support different ajv options for each schema #2269

Open qurafi opened 1 year ago

qurafi commented 1 year ago

What version of Ajv you are you using? 8.12.0

What problem do you want to solve? Currently is not possible to assign different compilation options to each specific schema. For example turning type coercing or allErrors.

I'm building a Vite/rollup plugin to compile json schemas using Ajv and I want to allow users to define different options on each schema on the same Ajv instance(so references can work)

What do you think is the correct solution to problem? I could think of two solutions for this but all has their own drawbacks and IMO this will not work well in my usecase

Will you be able to implement it? Of course I will help if it's necessary

qurafi commented 1 year ago

So taking a peak on how to implement this. I noticed that every compilation happens in https://github.com/ajv-validator/ajv/blob/45583fde112f80c06ba6ad5583b744ef22d0640a/lib/compile/index.ts#L111

I do a little experiment by overwriting this function module:


const compile_index = require("ajv/dist/compile/index");
const instance_opts = new WeakMap();
const schema_opts = new WeakMap();

const compileSchema = compile_index.compileSchema;

compile_index.compileSchema = function (sch) {
    const opts = schema_opts.get(sch.schema);
    if (opts) {
        if (!instance_opts.has(this)) {
            instance_opts.set(this, this.opts);
        }

        this.opts = { ...this.opts, ...opts };

        try {
            return compileSchema.call(this, sch);
        } finally {
            this.opts = instance_opts.get(this);
        }
    }

    return compileSchema.call(this, sch);
};

So any user could add different options to schema_opts

/** @param {import("ajv").Options} opts */
function addWithOptions(schema, opts) {
    opts && schema_opts.set(schema, opts);
    return ajv.addSchema(schema);
}

I tested this on multiple schemas including references. It worked well but there's some points about this:

errodrigues commented 5 months ago

This would be very useful