The json_serializer plugin handles serializing entire Sequel::Model
objects to JSON, as well as support for deserializing JSON directly into Sequel::Model
objects. It requires the json library, and can work with either the pure ruby version or the C extension.
Basic Example:
album = Album[1] album.to_json # => '{"id"=>1,"name"=>"RF","artist_id"=>2}'
In addition, you can provide options to control the JSON output:
album.to_json(only: :name) album.to_json(except: [:id, :artist_id]) # => '{"json_class"="Album","name"=>"RF"}' album.to_json(include: :artist) # => '{"id":1,"name":"RF","artist_id":2, # "artist":{"id":2,"name":"YJM"}}'
You can use a hash value with :include
to pass options to associations:
album.to_json(include: {artist: {only: :name}}) # => '{"id":1,"name":"RF","artist_id":2, # "artist":{"name":"YJM"}}'
You can specify a name for a given association by using an aliased expression as the key in the :include
hash
album.to_json(include: {Sequel.as(:artist, :singer)=>{only: :name}}) # => '{"id":1,"name":"RF","artist_id":2, # "singer":{"name":"YJM"}}'
You can specify the :root
option to nest the JSON under the name of the model:
album.to_json(root: true) # => '{"album":{"id":1,"name":"RF","artist_id":2}}'
You can specify JSON serialization options to use later:
album.json_serializer_opts(root: true) [album].to_json # => '[{"album":{"id":1,"name":"RF","artist_id":2}}]'
Additionally, to_json
also exists as a class and dataset method, both of which return all objects in the dataset:
Album.to_json Album.where(artist_id: 1).to_json(include: :tags)
If you have an existing array of model instances you want to convert to JSON, you can call the class to_json method with the :array option:
Album.to_json(array: [Album[1], Album[2]])
All to_json methods take blocks, and if a block is given, it will yield the array or hash before serialization, and will serialize the value the block returns. This allows you to customize the resulting JSON format on a per-call basis.
In addition to creating JSON, this plugin also enables Sequel::Model
classes to create instances directly from JSON using the from_json class method:
json = album.to_json album = Album.from_json(json)
The array_from_json class method exists to parse arrays of model instances from json:
json = Album.where(artist_id: 1).to_json albums = Album.array_from_json(json)
These does not necessarily round trip, since doing so would let users create model objects with arbitrary values. By default, from_json will call set with the values in the hash. If you want to specify the allowed fields, you can use the :fields option, which will call set_fields with the given fields:
Album.from_json(album.to_json, fields: %w'id name')
If you want to update an existing instance, you can use the from_json instance method:
album.from_json(json)
Both of these allow creation of cached associated objects, if you provide the :associations option:
album.from_json(json, associations: :artist)
You can even provide options when setting up the associated objects:
album.from_json(json, associations: {artist: {fields: %w'id name', associations: :tags}})
Note that active_support/json makes incompatible changes to the to_json API, and breaks some aspects of the json_serializer plugin. You can undo the damage done by active_support/json by doing:
module ActiveSupportBrokenJSONFix def to_json(options = {}) JSON.generate(self) end end Array.send(:prepend, ActiveSupportBrokenJSONFix) Hash.send(:prepend, ActiveSupportBrokenJSONFix)
Note that this will probably cause active_support/json to no longer work correctly in some cases.
Usage:
# Add JSON output capability to all model subclass instances (called before loading subclasses) Sequel::Model.plugin :json_serializer # Add JSON output capability to Album class instances Album.plugin :json_serializer
Classes and Modules
Public Class methods
Set up the column readers to do deserialization and the column writers to save the value in deserialized_values.
# File lib/sequel/plugins/json_serializer.rb 130 def self.configure(model, opts=OPTS) 131 model.instance_exec do 132 @json_serializer_opts = (@json_serializer_opts || OPTS).merge(opts) 133 end 134 end
Convert the given object to a JSON data structure using the given arguments.
# File lib/sequel/plugins/json_serializer.rb 151 def self.object_to_json_data(obj, *args, &block) 152 if obj.is_a?(Array) 153 obj.map{|x| object_to_json_data(x, *args, &block)} 154 else 155 if obj.respond_to?(:to_json_data) 156 obj.to_json_data(*args, &block) 157 else 158 begin 159 Sequel.parse_json(Sequel.object_to_json(obj, *args, &block)) 160 # :nocov: 161 rescue Sequel.json_parser_error_class 162 # Support for old Ruby code that only supports parsing JSON object/array 163 Sequel.parse_json(Sequel.object_to_json([obj], *args, &block))[0] 164 # :nocov: 165 end 166 end 167 end 168 end