Jsonity
The most natural language for building JSON in Ruby
Overview
= ->(t) {
t.(inherit: true) { ||
.total_pages
.current_page
}
}
Jsonity.build { |t|
t <= @users
t[].users!(inherit: true) { |user|
user.id
user.age
user.full_name { |u| [u.first_name, u.last_name].join ' ' }
user.avatar? { |avatar|
avatar.image_url
}
}
t.(&)
}
#=> {
# "users": [
# {
# "id": 1,
# "age": 21,
# "full_name": "John Smith",
# "avatar": {
# "image_url": "http://example.com/john.png"
# }
# },
# {
# "id": 2,
# "age": 37,
# "full_name": "William Northington",
# "avatar": {
# "image_url": "http://example.com/william.png"
# }
# },
# {
# "id": 3,
# "age": 29,
# "full_name": "Samuel Miller",
# "avatar": {
# "image_url": "http://example.com/samuel.png"
# }
# }
# ],
# "meta": {
# "total_pages": 1,
# "current_page": 1
# }
# }
Usage
Make sure to add the gem to your Gemfile.
gem 'neo_json'
Start writing object:
Jsonity.build { |t|
# ...
}
Object assignment
To declare the data object for use:
t <= @user
Attribute nodes
Basic usage of defining simple attributes:
t.id # @user.id
t.age # @user.age
Or you can use custom attributes in flexible ways:
t.full_name { |u| [u.first_name, u.last_name].join ' ' } # u = @user
t.russian_roulette { rand(1..10) } # block parameter isn't required
t.with_object(Time) { |t| t.now } # now, t = Time
t.seventeen 17 # block can be omitted
Aliased attributes works well as you expected:
# show `id` as `my_id`
t.my_id &:id
Automatic attributes inclusion
If you set attr_json in any class, the specified attributes will automatically be included:
class Sample < Struct.new(:id, :foo)
attr_json :id, :foo
end
@sample = Sample.new 123, 'foo!'
Jsonity.build { |t|
t.sample!(@sample) { |t|
# leave empty inside
}
}
#=> {
# "sample": {
# "id": 123,
# "foo": "foo!"
# }
# }
Hash nodes
With name suffixed with !, nested object can be included:
t.user! { |user|
user.name # @user.name
user.avatar! { |avatar|
avatar.image_url # @user.avatar.image_url
avatar.width # @user.avatar.width
avatar.height # @user.avatar.height
}
}
If @user.avatar = nil, the output will be like this:
{
"user": {
"name": "John Smith",
"avatar": {
"image_url": null,
"width": null,
"height": null
}
}
}
On the other hand, use ? as suffix, the whole object become null:
t.user! { |user|
user.name
user.avatar? { |avatar|
avatar.image_url
avatar.width
avatar.height
}
}
and the output will be:
{
"user": {
"name": "John Smith",
"avatar": null
}
}
Explicitly set an object to use inside a block:
t.home?(@user.hometown_address) { |home|
home.street # @user.hometown_address.street
home.zip
home.city
home.state
}
Or blocks can inherit the parent object:
t.user! { |user|
t.my!(inherit: true) { |my|
my.name # @user.name
}
}
Array nodes
Including a collection of objects, just use t[] and write the same syntax of hash node:
t[].friends! { |friend|
friend.name
}
and the output JSON will be:
{
"friends": [
{
name: "John Smith"
}
]
}
Similar to hash nodes in naming convention,
if @user.friends = nil nodes suffix with ! will be an empty array [], in contrast, some with ? will be null.
Also passing the object or inheritance can be done in the same way as hash nodes.
Mixin / Scope
Since Jsonity aim to be simple and light, use plain Proc to fullfill functonality of mixin.
= ->(t) {
t.created_at
t.updated_at
}
and then,
t.user! { |user|
user.(&)
}
In case you might use different object in mixin, you can pass the object in the first argument:
t.(@other_user, &)
So you take this functonality for scope:
t.(@other_user) { |other_user|
other_user.name
}
Mixining nested object and merging
= ->(t) {
t. { ||
.total_pages
.current_page
}
}
and use this mixin like:
t[].people!(@people) { |person|
# ...
}
t.(@people, &)
t. { ||
.total_count @people.count
}
the output become:
{
"people": [
// ...
],
"meta": {
"total_pages": 5,
"current_page": 1,
"total_count": 123
}
}
Notice that two objects meta! got merged.
Conditions
Simply you can use if or unless statement inside the block:
t[].people! { |person|
unless person.private_member?
person.name
person.age
end
person.cv if person.looking_for_job?
}
With Rails
Helper method is available for rendering with Jsonity:
render_json(status: :ok) { |t|
# ...
}
License
This project is copyright by Creasty, released under the MIT lisence.
See LICENSE file for details.