voxpupuli / json-schema

Ruby JSON Schema Validator
MIT License
1.52k stars 241 forks source link

option to remove additional properties #453

Open ngouy opened 3 years ago

ngouy commented 3 years ago

It would be awesome to leverage this gem to skip altogether the params permissions in the controller

Today we can almost do so if our API doesn't allow additional properties. Indeed, if you use strict: true when validating incoming params against a schema, you can assume that you don't need to recheck (the real issue is more: re-write at a different place) your params when using them into your rails CRUD controller (permitted params)

The issue comes when you don't want to raise an error if extra params are given, but you still want to "extract" only the "permitted" (or in the JSON schema case the "described") params

I see here https://www.rubydoc.info/gems/json-schema/2.4.1#Validate_a_JSON_object_against_a_JSON_schema_object__while_inserting_default_values_from_the_schema That some options are modifying the given data to check.

Could it be a good idea to provide a new option such as remove_additional_properties: true that would remove the non "described" properties (not present in the json schema) if the data end up being valid against the tested schema

This could solve the issue :

schema = {
  "type" => "object",
  "required" => ["a", "b"],
  "properties" => {
    "a" => {"type" => "integer"},
    "b" => {
      "type" => "object",
      "required" => ["d"],
      "properties": {
        "d" => {"type" => "integer"},
      },
      "additionalProperties": false,
  }
}

JSON::Validator.validate(schema, data)
# true # valid but no modification in data
# data = {
#  "a" => 5,
#   "b" => {
#     "d" => 2
#   },
#   "j" => "woops"
# }

JSON::Validator.validate(schema, data, :remove_additional_properties => true)
# true # valid and we removed "non described" additional param
# data = { 
#  "a" => 5,
#   "b" => {
#     "d" => 2
#   },
# }

# If additional params are given where additionalParams is explicitly to false, an finite enum, or :strict option is used, it fails

data = {
  "a" => 5,
  "b" => {
    "d" => 2,
    "e" => "nope"
  },
}

JSON::Validator.validate(schema, data, :remove_additional_properties => true)
# false
# data = {
#  "a" => 5,
#   "b" => {
#     "d" => 2,
#     "e" => "nope",
#   },
# }

additionalProperties: false => raises an error and doesn't modify the data additionalProperties: true => doesn't raises error and doesn't modify the data additionalProperties: nil => doesn't raises error and modify the data additionalProperties: [enum] => TBD (raises an error and doesn't modify the data OR doesn't raises error and remove additional keys that are not present in the additionalProperties enum) // preference for the first one