Validate JSON attribute of a Model

Gursimranjit Singh
Jan 12 · 3 min read

I was creating a feature where I need to validate the JSON type attribute of a table so that it has valid schema. I need to validate it before all creations and updations processes of that Model.

So lets begin with the workflow.

1. Initially, I created a migration to create a table with a JSON attribute.

create_table :system_configurations do |t|    t.string :name    t.json :day_timingsend

This schema of this day_timings attribute is like

day_timings: {    Monday:["9:00 AM", "10:00 AM"],    Tuesday:["9:00 AM", "11:00 AM"],    Wednesday:["10:00 AM", "1:00 PM"],    Thursday:["9:00 AM", "2:00 PM"],    Friday:["9:00 AM", "1:00 PM"],    Saturday:["11:00 AM", "1:00 PM"],    Sunday:["9:00 AM", "10:00 AM"]}

2. Then I did some R&D and find this gem ‘json-schema’, which fulfils all my needs.

You can go through this URL for detail information.

3. Then, I created the DAY_TIMINGS_VALIDATION_SCHEMA constant in config/initializers/constant.rb file (to have better app structure) which define the complete schema.

# config/initializers/constant.rbDAY_TIMINGS_VALIDATION_SCHEMA = {    type: "object",    required: [        "Monday",        "Tuesday",        "Wednesday",        "Thursday",        "Friday",        "Saturday",        "Sunday"    ],    properties: {        Monday: FROM_TO_TIME_SCHEMA,        Tuesday: FROM_TO_TIME_SCHEMA,        Wednesday: FROM_TO_TIME_SCHEMA,        Thursday: FROM_TO_TIME_SCHEMA,        Friday: FROM_TO_TIME_SCHEMA,        Saturday: FROM_TO_TIME_SCHEMA,        Sunday: FROM_TO_TIME_SCHEMA    }}FROM_TO_TIME_SCHEMA = {    type: "array",    items: {        type: "string",        pattern: "^(1[0-2]|0?[1-9]):([0-5]?[0-9])( ?[AaPp][Mm])?$"    },    minItems: 2,    maxItems: 2}

- type: defines what type of input it is.

- required: defines which properties are necessary in this object type.

- properties: defines the structure of object type. In this, it says that it has Monday, Tuesday, etc days as key of the object.

- FROM_TO_TIME_SCHEMA: defines the further schema of nested properties.


-type: defines what type of input it is. This time its of array type.

- minItems, maxItems: define the minimum and maximum count of items in the array.

-items: defines the format of each item in that array i.e in this case it says its of string type with defined pattern.

4. Then, I added custom validation in the SystemConfiguration Model so that before create and update, the app automatically validate the schema by using the predefined constant DAY_TIMINGS_VALIDATION_SCHEMA and proceed further.

validate :day_timings_schema_checkdef day_timings_schema_check errors.add(:day_timings, "Invalid Day Timing Format. Please enter a valid Time Format.") unless JSON::Validator.validate(DAY_TIMINGS_VALIDATION_SCHEMA, day_timings)end

JSON::Validator.validate is a method that takes 2 parameters, the JSON schema followed by the attribute which you want to validate(Here the attribute is the day_timings attribute of system_configuration model). Its return type is boolean(true/false).

You can also use bang mark with validate(validate!) to through exception if the JSON is invalid.

JSON::Validator.validate!(DAY_TIMINGS_VALIDATION_SCHEMA, day_timings)

By this way, I was able to successfully validate my JSON attribute.

Thanks for reading. :)

Gursimranjit Singh

Written by

Enthusiastic Software Engineer

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade