A Crystal Library which extends JSON::Serializable to allow JSON to be generated via method calls, instead of requiring the use of variables.
NOTE: This library only supports Serialization. Deserialization to Fake FIelds is not possible.
Installation
-
Add the dependency to your
shard.yml
:dependencies: serializable-fake: github: ryan-kraay/json-serializable-fake
-
Run
shards install
Usage
require "json"
require "json-serializable-fake"
class Sum
include JSON::Serializable
include JSON::Serializable::Fake
property a : UInt32
property b : UInt32
def initialize(@a, @b)
end
@[JSON::FakeField]
def sum(json : ::JSON::Builder) : Nil
json.number(a + b)
end
end
s = Sum.new(10, 5)
puts s.to_json # => { "a": 10, "b": 5, "sum": 15 }
Additional documentation can be found here.
Features
This library was born out of desire to use classes and members to construct JSON object, but also to use methods to construct JSON fields that do not necessarily need to be stored as members in a class definition.
Some additional features:
JSON::FakeField(key: <name>)
: creates a field with an explicit name (by default it uses the method name)JSON::FakeField(supress_key: true)
: iftrue
no json field will be implicitly added. This allows the method to create multiple json fields or an entire JSON document usingJSON::Builder
.- Integrates with
JSON::Serializable
andJSON::Serializable::Unmapped
: this allows you to mix-and-match and create nestedJSON::Serializable
andJSON::Serializable::Fake
objects. - It is possible to change, manipulate, or remove
JSON::Serializable
fields at runtime.
NOTE: The use of JSON::Serializable
relies on an "opt-out" feature (ie: JSON::Field(ignore_serialization: true)]
). Meaning all instance variables will be added to the json document, unless you explicitly "opt-out".. JSON::Serializable::Fake
relies on an "opt-in" for instance methods. Meaning that only those instance methods which contain the JSON::FakeField
annotation will be added to the json document.
Advanced Example
require "json"
require "json-serializable-fake"
class User
include JSON::Serializable
include JSON::Serializable::Fake
property first : String
property last : String
property password : String
@[JSON::FakeField]
def user(json : ::JSON::Builder) : Nil
json.string( (@first + @last).downcase )
end
def initialize(@first, @last, @password)
end
end
class SecuredUser < User
property age : UInt32
# replace our user() implementation via simple inheritance
def user(json : ::JSON::Builder) : Nil
json.string("retracted")
end
@[JSON::FakeField(key: password)]
def hide_password(json : ::JSON::Builder) : Nil
json.string("******")
end
@[JSON::FakeField(suppress_key: true)]
def age(json : ::JSON::Builder) : Nil
# Only show the age, if the user is over 18
if age > 18
json.field "age", @age
end
end
def initialize(@first, @last, @age, @password)
end
end
user = User.new("John", "Doe", "hunter2")
puts user.to_json # => {"first":"John","last":"Doe","password":"hunter2","user":"johndoe"}
child = SecuredUser.new("Jimmy", "Doe", 5_u32, "hunter2")
puts child.to_json # => {"first":"Jimmy","last":"Doe","password":"******","user":"retracted"}
puts child.password # => hunter2
adult = SecuredUser.new("Jane", "Doe", 24_u32, "hunter2")
puts adult.to_json # => {"first":"Jane","last":"Doe","password":"******","age":24,"user":"retracted"}
puts adult.password # => hunter2
Limitations
- This library only supports JSON Serialization (not YAML). There is no technical reason for this limitation, just a lack of time.
- This library only support Serialization. Deserializing into a method call is not support. Again, there is no technical limitation, only time. However,
JSON::FakeFields
will appear asobjecct.json_unmapped[<fakefield>]
, whenJSON::Serializable::Unmapped
is used.
Contributing
- Fork it (https://github.com/ryan-kraay/json-serializable-fake/fork)
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request