Skip to content

odelbos/saphyr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Testing Gem Version License

Saphyr

Simple DSL to design validation schemas for JSON document (or Hash/Array structure).

Features :

  • Provide a DSL to define validation schemas
  • Provide some standard field types
  • Define you own custom field type
  • Conditional fields validation
  • Field casting (before validation)

Standard field types :

  • Integer, Float, String, Boolean
  • Email
  • URI
  • URL
  • Base64
  • ipv4 / ipv6
  • Country (ISO-3166-1 alpha 2/3)
  • Language (ISO-639-1, ISO-639-2)
  • DateTime

See examples folder for some basic usages.

Generate documentation

Generate the documentation in ./doc folder:

$ yard 

Start a http server and serve the documentation:

$ yard server 

Run tests

rspec 

Installation

Add it to your Gemfile:

$ bundle add saphyr $ bundle install 

Install the gem (globally):

$ gem install saphyr 

Example of Usage

Some short examples to give a picture of Saphyr:

The most simple usage

data = { # --- Rules --- "id" => 236, # Integer > 0 "type" => 1, # Integer, possible values are : 1, 2 or 3 "price" => 32.10, # Float > 0 "name" => "my item" # String with: 5 >= size <= 15 "active" => true # Boolean } class ItemValidator < Saphyr::Validator field :id, :integer, gt: 0 field :type, :integer, in: [1, 2, 3] # Field name can be a field "price", :float, gt: 0 # Symbol or a String field "name", :string, min: 5, max: 15 field :active, :boolean end
v = ItemValidator.new if v.validate data puts "Validation : SUCCESS", "\n" else puts "Validation : FAILED", "\n" Saphyr::Helpers::Format.errors_to_text v.errors end # Or use: v.parse_and_validate json

A more advanced usage

data = { # --- Rules --- "id" => 236, # Integer > 0 "name" => "my item", # String with: 5 >= size <= 15 "uploads" => [ # This array can only have 2 or 3 elements { "id" => 34, # Interger > 0 "name" => "orig.gif", # String, with: 7 <= size <= 15 "mime" => "image/gif", # String, possible values: ['image/jpeg', 'image/png', 'image/gif'] "size" => 753745, # Integer > 0 "timestamps" => { "created_at" => 1665241021, # Integer > 0 (unix timestamp) "modified_at" => 1665241021 # Integer > 0 (unix timestamp) } }, { "id" => 376, "name" => "medium.jpg", "mime" => "image/png", "size" => 8946653, "timestamps" => { "created_at" => 1669215446, "modified_at" => 1670943462 } } ], "timestamps" => { "created_at" => 1669215446, "modified_at" => 1670943462 }, "active" => true, } class ItemValidator < Saphyr::Validator schema :timestamp do field :created_at, :integer, gt: 0 field :modified_at, :integer, gt: 0 end schema :upload do field :id, :integer, gt: 0 field :name, :string, min: 7, max: 15 field :mime, :string, in: ['image/jpeg', 'image/png', 'image/gif'] field :size, :integer, gt: 0 field :timestamps, :schema, name: :timestamp end field :id, :integer, gt: 0 field :name, :string, min: 7, max: 15 field :uploads, :array, min: 2, max: 3, of_schema: :upload field :timestamps, :schema, name: :timestamp field :active, :boolean, eq: true end

Default field value

data = { # --- Rules --- "id" => 236 # Integer > 0 # field 'active' is missing } class ItemValidator < Saphyr::Validator field :id, :integer, gt: 0 field :active, :boolean, default: true end
v = ItemValidator.new v.validate data # Will success

After the validation, the active field is added to data with his default value:

data = { "id" => 236, "active" => true }

When root is an array

By default validator root are set to :object, but this can be customized.

In this case, only one virtual field must be defined : :_root_ and it must be of type :array

Example with :of_type :

data = ['fr', 'en', 'es'] class ItemValidator < Saphyr::Validator root :array field :_root_, :array, min: 2, max: 5, of_type: :string, opts: {len: 2} end

Example with :of_schema :

data = [ { "id" => 12, "label" => "tag1" }, { "id" => 15, "label" => "tag2" }, ] class ItemValidator < Saphyr::Validator root :array schema :tag do field :id, :integer, gt: 0 field :label, :string, min: 2, max: 30 end field :_root_, :array, min: 2, max: 4, of_schema: :tag end

Conditional fields

Sometime, we can have different fields depending on a specitic field value.

data_1 = { "id" => 145, "type" => "file", "name" => "Lipsum ...", # Condtionals fields: "mime" => "image/png", # must be defined only if type == 'file' } data_2 = { "id" => 145, "type" => "post", "content" => "Lipsum ...", # Condtionals fields: "author" => "Lipsum ...", # must be defined only if type == 'post' }

Example of Validator with conditional fields:

class ItemValidator < Saphyr::Validator field :id, :integer, gt: 0 field :type, :string, in: ['post', 'file'] # Using a method call conditional :is_file? do # Will call 'is_file?' method to check the conddtion field :name, :string, min: 2 field :mime, :string, in: ['image/png', 'image/jpg'] end # Using a lambda conditional -> { get(:type) == 'post' } do field :content, :string field :author, :string end private def is_file? # Must return: true | false get(:type) == 'file' end end

Field casting

data = { "id" => 1, "name" => "Lipsum ...", "created_at" => "2023-10-26 10:57:05.29685 +0200", # Cast to unix timestamp "active" => "Yes", # Cast to Boolean }

Casting is applied before validation.

class ItemValidator < Saphyr::Validator # Using a method call cast :created_at, :cast_created_at # Using a lambda cast :active, -> (value) { return true if ['yes', 'y'].include? value.downcase return false if ['no', 'n'].include? value.downcase value # Unknown value, returning it back } # ----- field :id, :integer, gt: 0 field :name, :string, min: 5 field :created_at, :integer, gt: 0 field :active, :boolean private def cast_created_at(value) begin return DateTime.parse(value).to_time.to_i end value end end

Global schemas:

Saphyr.register do schema :timestamp do field :created_at, :integer, gt: 0 field :modified_at, :integer, gt: 0 end end class ItemValidator < Saphyr::Validator # .... field :timestamps, :schema, name: :timestamp end class PostValidator < Saphyr::Validator # .... field "timestamps", :schema, name: :timestamp end

Documentation and HowTo

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/odelbos/saphyr.

License

The gem is available as open source under the terms of the MIT License.

Roadmap

  • Add field class
  • Add internal basic fields (integer, float, string, boolean, array)
  • Add validator class
  • Add local and global schema
  • Add validation engine
  • Add conditional field
  • Add field casting
  • Add default value to field
  • Add more internal fields (b64, b62, uuid, ipv4, ipv6, ...)

Author

@odelbos

About

Simple DSL to design validation schemas for JSON document (or Hash / Array structure).

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published