- Notifications
You must be signed in to change notification settings - Fork1
JSON Schema based serializer for ruby
License
Narazaka/json-schema-serializer
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
JSON Schema based serializer
Add this line to your application's Gemfile:
gem'json-schema-serializer'
And then execute:
$ bundleOr install it yourself as:
$ gem install json-schema-serializerrequire"json/schema/serializer"schema={type:"object",properties:{id:{type:"integer"},name:{type:"string"},fuzzy:{type:["string","integer","null"]},},required:["id"],}serializer=JSON::Schema::Serializer.new(schema)serializer.serialize({id:"42",name:"me",foo:"bar",fuzzy:"1000"})# => {"id"=>42, "name"=>"me", "fuzzy"=>"1000"}# "42" -> 42! type coerced!serializer.serialize({id:"42",name:"me",fuzzy:42})# => {"id"=>42, "name"=>"me", "fuzzy"=>42}serializer.serialize({id:"42",name:"me"})# => {"id"=>42, "name"=>"me", "fuzzy"=>nil}# multiple type auto select!serializer.serialize({})# => {"id"=>0, "name"=>nil, "fuzzy"=>nil}# nil -> 0! required property's type coerced!serializer.serialize({id:10,name:"I don't need null keys!"}).compact# => {"id"=>10, "name"=>"I don't need null keys!"}# compact it!classAdefid42endendserializer.serialize(A.new)# => {"id"=>42, "name"=>nil, "fuzzy"=>nil}# method also allowedclassSchemadeftype:stringendendserializer2=JSON::Schema::Serializer.new(Schema.new)serializer2.serialize(32)# => "32"# non-hash schema allowed## object injector allowed!#classFooSerializerdefinitialize(model)@model=modelenddeffirst@model.firstenddefcount@model.sizeendendserializer_injected=JSON::Schema::Serializer.new({type::object,inject::Foo,properties:{first:{type::integer},count:{type::integer},},},{inject_key::inject,injectors:{Foo:FooSerializer,},},)serializer_injected.serialize([1,2,3])# => {"first"=>1, "count"=>3}## object injector with context#classBarSerializerdefinitialize(model,context=nil)@model=model@context=contextenddefid@model[:id]enddefscore@context[@model[:id]]endendinject_context={1=>100,2=>200,}serializer_injected_with_context=JSON::Schema::Serializer.new({type::object,inject::Bar,properties:{id:{type::integer},score:{type::integer},},},{inject_key::inject,injectors:{Bar:BarSerializer,},inject_context:inject_context,},)serializer_injected_with_context.serialize({id:1})# => { "id" => 1, "score" => 100 }## inject in serializer#classParentSerializerincludeJSON::Schema::Serializer::WithContextdefinitialize(model,context=nil)@model=model@context=contextenddefid@model[:id]enddefscore@context[:parent_scores][@model[:id]]enddefchild# it can be# with_context(context) { data }# with_context(data, context)# with_context(data: data, context: context)with_context(@context.merge(child_scores:{1=>100,2=>200}))do@model[:child]endendendclassChildSerializerdefinitialize(model,context=nil)@model=model@context=contextenddefid@model[:id]enddefscore@context[:child_scores][@model[:id]]endendserializer_injected_with_context_in_serializer=JSON::Schema::Serializer.new({type::object,inject::Parent,properties:{id:{type::integer},score:{type::integer},child:{type::object,inject::Child,properties:{id:{type::integer},score:{type::integer},},},},},{inject_key::inject,injectors:{Parent:ParentSerializer,Child:ChildSerializer,},inject_context:{1=>10,2=>20},},)serializer_injected_with_context_in_serializer.serialize({id:1,child:{id:2}})# => { "id" => 1, "score" => 10, "child" => { "id" => 2, "score" => 200 } }## also you can inject context with arraylike data#classItemsSerializerincludeJSON::Schema::Serializer::WithContextdefinitialize(models,context=nil)@models=models@context=contextenddefmap(&block)context=(@context ||{}).merge(scores:{...})@models.map{ |model|block.call(with_context(model,context))}# CAUTION!# not like below!# with_context(@models.map(&block), context)# with_context(context) { @models.map(&block) }endend## inject model can initialize by keywords#classKeywordSerializerdefinitialize(data:,context:nil)@data=data@context=contextend ...endserializer_with_keyword_init_inject=JSON::Schema::Serializer.new({type::object,inject::Keyword,properties:{ ...},},{inject_key::inject,injectors:{Keyword:KeywordSerializer,Child:ChildSerializer,},inject_by_keyword:true,# <- keyword_init!},)
"additionalProperties" is allowed but must be a schema object orfalse. (nottrue)
If "additionalProperties" does not exists, this serializer works as{ additionalProperties": false }.
JSON::Schema::Serializer does not resolve$ref so use external resolver.
withhana andjson_refs gem example:
require"hana"require"json_refs"require"json/schema/serializer"schema={"type"=>"object","properties"=>{"foo"=>{"type"=>"integer"},"bar"=>{"$ref"=>"#/properties/foo"},},}serializer=JSON::Schema::Serializer.new(JsonRefs.(schema))serializer.serialize({foo:0,bar:"42"})# => {"foo"=>0, "bar"=>42}# resolver option also availabledefwalk(all,part)ifpart.is_a?(Array)part.map{ |item|walk(all,item)}elsifpart.is_a?(Hash)ref=part["$ref"] ||part[:"$ref"]ifrefHana::Pointer.new(ref[1..-1]).eval(all)elsepart.map{ |k,v|[k,walk(all,v)]}.to_hendelsepartendendserializer2=JSON::Schema::Serializer.new(schema["properties"]["bar"],{resolver:->(part_schema)dowalk(JsonRefs.(schema),part_schema))end})
The initializer.
JSON schema object. The serializer tries schema["type"], schema[:type] and schema.type!
options
schema object$ref resolver
input key transform
new({type::object,properties:{userCount:{type::integer},},},{schema_key_transform_for_input:->(name){name.underscore}}).serialize({user_count:1}) =={"userCount"=>1}
output key transform
new({type::object,properties:{userCount:{type::integer},},},{schema_key_transform_for_output:->(name){name.underscore}}).serialize({userCount:1}) =={"user_count"=>1}
options[:injectors] [Hashlike<String, Class>, Class], options[:inject_key] [String, Symbol], options[:inject_context] [any], options[:inject_by_keyword] [Boolean]
If schema has inject key, the serializer treats data byinjectors[inject_key].new(data) (orinjectors.send(inject_key).new(data)).
And ifinject_context is present,injectors[inject_key].new(data, inject_context) (orinjectors.send(inject_key).new(data, inject_context)).
And ifinject_by_keyword is true,new(data, inject_context) will benew(data: data, context: inject_context).
See examples inUsage.
CAUTION: In many case you should define thenil? method in the injector class because Injector always initialized byInjector.new(obj) even if obj == nil.
If data is null, always serialize null.
new({type::string},{null_through:true}).serialize(nil) ==nil
If data == "" in integer or number schema, returns nil.
new({type::integer},{empty_string_number_coerce_null:true}).serialize("") ==nil
If data == "" in boolean schema, returns nil.
new({type::boolean},{empty_string_boolean_coerce_null:true}).serialize("") ==nil
If specified, boolean schema treats!false_values.include?(data).
new({type::boolean},{false_values:Set.new([false])}).serialize(nil) ==true
If true, boolean schema treats onlytrue to betrue.
new({type::boolean},{no_boolean_coerce:true}).serialize(1) ==false
If true, array or object schema does not accept primitive data and returns empty value.
new({type::object},{guard_primitive_in_structure:true}).serialize(1) =={}new({type::object},{guard_primitive_in_structure:true,null_through:true}).serialize(1) ==nil
Serialize the object data by the schema.
Serialize target object. The serializer tries data["foo"], data[:foo] and data.foo!
#with_context!(data, context), #with_context!(data: data, context: context), #with_context!(context) { data }
If you usewith_context!(data, context) as the return value of the serializer, then "child" serializer can use that context.
See examples inUsage.
Zlib License
After checking out the repo, runbin/setup to install dependencies. Then, runrake spec to run the tests. You can also runbin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, runbundle exec rake install. To release a new version, update the version number inversion.rb, and then runbundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the.gem file torubygems.org.
Bug reports and pull requests are welcome on GitHub athttps://github.com/Narazaka/json-schema-serializer.
About
JSON Schema based serializer for ruby
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors2
Uh oh!
There was an error while loading.Please reload this page.