-
I have a AR class "Person" I mean something like that: JSI::JSICoder.new(PersonContract).serialize(active_record_person) |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
It looks like you mean to limit the serialization of a record. JSICoder is for serialization between database columns (of either stringified or native JSON) and record attributes - it doesn't do anything with whole records. JSI can filter instances based on schemas describing them, which I'll demonstrate below - but it needs JSON compatible types to instantiate. You can get that from AR's builtin serialization, or other gems, but that's outside JSI's scope. From there, JSI has methods to select a document's nodes: jsi_select_descendents_leaf_first and node_first. These can select based on what schemas (or lack thereof) describe a given node. Some examples follow, and I put a full standalone script in this gist in case anybody might want to run/tweak/play with it (I might add this to the repo in an Given this model: ActiveRecord::Schema.define do
create_table :users do |table|
table.column :name, :string
table.column :email, :string
table.column :age, :integer
table.column :secret, :string
end
end
class User < ActiveRecord::Base
end and this record user = User.create!(
name: 'Me',
email: 'me@here',
age: 0,
secret: '🤐',
) converted to JSON compatible types using ActiveRecord's builtin serialization user_json = user.serializable_hash
# → {"id" => 1, "name" => "Me", "email" => "me@here", "age" => 0, "secret" => "🤐"} We can filter that using a schema which only describes attributes that are to be included: user_schema = JSI.new_schema({
"$schema" => "http://json-schema.org/draft-07/schema",
"type" => "object",
"properties" => {
"id" => {},
"name" => {"type" => "string"},
# ❌ no "email"
"age" => {"type" => "integer", "minimum" => 1},
# ❌ no "secret"
},
})
user_jsi = user_schema.new_jsi(user_json)
user_filtered = user_jsi.jsi_select_descendents_leaf_first do |node|
# reject nodes which have no schemas that describe them
!node.jsi_schemas.empty?
end
# → #{<JSI> "id" => 1, "name" => "Me", "age" => 0} Or a schema which specifically excludes attributes indicated by a user_schema = JSI.new_schema({
"$schema" => "http://json-schema.org/draft-07/schema",
"type" => "object",
"properties" => {
"id" => {},
"name" => {"type" => "string"},
# ✅ "email" is not specifically excluded
"age" => {"type" => "integer", "minimum" => 1},
"secret" => false, # ❌ will exclude "secret"
},
})
user_jsi = user_schema.new_jsi(user_json)
user_filtered = user_jsi.jsi_select_descendents_leaf_first do |node|
# reject nodes described by `false` schema
!node.jsi_schemas.any? { |s| s.schema_content == false }
end
# → #{<JSI> "id" => 1, "name" => "Me", "email" => "me@here", "age" => 0} You could also use Or you could limit the selection to what passes validation - usually a bad idea, I think, but it probably has some use case and is worth illustrating: user_schema = JSI.new_schema({
"$schema" => "http://json-schema.org/draft-07/schema",
"type" => "object",
"properties" => {
"id" => {},
"name" => {"type" => "string"},
# ✅ "email" has no schema, nothing makes it invalid
"age" => {"type" => "integer", "minimum" => 1}, # ❌ age=0 fails validation
"secret" => false, # ❌ nothing is valid against `false` schema
},
})
user_jsi = user_schema.new_jsi(user_json)
user_filtered = user_jsi.jsi_select_descendents_leaf_first do |node|
node.jsi_valid?
end
# → #{<JSI> "id" => 1, "name" => "Me", "email" => "me@here"} There is quite a variety of ways JSON Schema might describe an instance, so there isn't exactly one general case of how filtering an instance by schema should work. I hope these examples show the flexibility of the select_descendent methods for filtering. |
Beta Was this translation helpful? Give feedback.
It looks like you mean to limit the serialization of a record. JSICoder is for serialization between database columns (of either stringified or native JSON) and record attributes - it doesn't do anything with whole records.
JSI can filter instances based on schemas describing them, which I'll demonstrate below - but it needs JSON compatible types to instantiate. You can get that from AR's builtin serialization, or other gems, but that's outside JSI's scope.
From there, JSI has methods to select a document's nodes: jsi_select_descendents_leaf_first and node_first. These can select based on what schemas (or lack thereof) describe a given node. Some examples follow, and I put a full standalo…