Git Product home page Git Product logo

saphyr's Introduction

Testing Gem Version License

Saphyr

The purpose of Saphyr gem is to provide a simple DSL to easily and quickly design a validation schema for JSON document.

Note :

There are already a bunch of gem doing this job, like: json-schema, json_schema, json_schemer all based on the JSON Standard to define a validation schema. It's a really nice crafted standard but his usage is not really intuitive.

Actually the Saphyr gem volontary does not support the json-schema standard to describe the validation schema and focus on simplicity with an easy to use DSL.

Generate documentation

Generate the documentation in ./doc folder:

$ yard

Start a http server and serve the documentation:

$ yard serve

Run tests

rspec
rake
rake spec

Installation

Add it to your Gemfile:

$ bundle add saphyr
$ bundle install

Install the gem:

$ 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 :price,   :float,    gt: 0
  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

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, :created_at_cast

  # 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 created_at_cast(value)
      begin
        return DateTime.parse(value).to_time.to_i
      end
      value
    end
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, ipv4, ...)

Author

@odelbos

saphyr's People

Contributors

odelbos avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.