I am dabbling with json fields in Postgres. So I am using activerecord for most validation. But, I'd like to add a json field and be able to validate that. Is there a clean way to do this? I guess I could always create my own validation function but it seems like there would be a better way that may take advantage of json schemas? Has anyone had success with this?
You can use the json-schema gem:
schema = {
"type" => "object",
"required" => ["a"],
"properties" => {
"a" => {"type" => "integer"}
}
}
JSON::Validator.validate(schema, { "a" => 5 })
# => true
JSON::Validator.validate(schema, { "a" => "five" })
# => false
Note that this a validator in the broader sense of the term - not a validator that can be directly used with ActiveRecord.
Writing a custom ActiveModel validator is pretty easy though:
require "json-schema"
class SchemaValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
# Looks for a JSON schema as a class constant
c = "#{attribute.upcase}_SCHEMA"
begin
schema = record.class.const_get(c)
rescue NameError => e
# re-raise exception with a more descriptive message
raise(
$!,
"Expected #{record.class.name}::#{c} to declare a JSON Schema for #{attribute}",
$!.backtrace
)
end
unless JSON::Validator.validate(schema, value)
record.errors.add(attribute, 'does not comply to JSON Schema')
end
end
end
We can then use it like so:
class Thing < ActiveRecord::Base
FOO_SCHEMA = {
"type" => "object",
"required" => ["a"],
"properties" => {
"a" => {"type" => "integer"}
}
}
validates :foo, schema: true
end
You could also check json at database level. As far as I know there are two libraries that validate JSONs in PostgreSQL:
Once you have installed one of them you could do:
ALTER TABLE my_table ADD CONSTRAINT data_is_valid CHECK (validate_json_schema('{/*your schema here */}', my_json));
if you are using Postgres JSON schema, and:
ALTER TABLE my_table ADD CONSTRAINT data_is_valid CHECK (is_jsonb_valid('{/*your schema here */}', my_json));
if you are using is_jsonb_valid.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With