/usr/lib/ruby/vendor_ruby/sequel/plugins/json_serializer.rb is in ruby-sequel 3.33.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | module Sequel
tsk_require 'json'
module Plugins
# 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
# # => '{"json_class"=>"Album","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)
# # => '{"json_class":"Album","id":1,"name":"RF","artist_id":2,
# "artist":{"json_class":"Artist","id":2,"name":"YJM"}}'
#
# You can use a hash value with <tt>:include</tt> to pass options
# to associations:
#
# album.to_json(:include=>{:artist=>{:only=>:name}})
# # => '{"json_class":"Album","id":1,"name":"RF","artist_id":2,
# "artist":{"json_class":"Artist","name":"YJM"}}'
#
# You can specify the <tt>:root</tt> option to nest the JSON under the
# name of the model:
#
# album.to_json(:root => true)
# # => '{"album":{"id":1,"name":"RF","artist_id":2}}'
#
# In addition to creating JSON, this plugin also enables Sequel::Model
# objects to be automatically created when JSON is parsed:
#
# json = album.to_json
# album = JSON.parse(json)
#
# In addition, you can update existing model objects directly from JSON
# using +from_json+:
#
# album.from_json(json)
#
# This works by parsing the JSON (which should return a hash), and then
# calling +set+ with the returned hash.
#
# Additionally, +to_json+ also exists as a class and dataset method, both
# of which return all objects in the dataset:
#
# Album.to_json
# Album.filter(:artist_id=>1).to_json(:include=>:tags)
#
# 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
module JsonSerializer
# Set up the column readers to do deserialization and the column writers
# to save the value in deserialized_values.
def self.configure(model, opts={})
model.instance_eval do
@json_serializer_opts = (@json_serializer_opts || {}).merge(opts)
end
end
# Helper class used for making sure that cascading options
# for model associations works correctly. Cascaded options
# work by creating instances of this class, which take a
# literal JSON string and have +to_json+ return it.
class Literal
# Store the literal JSON to use
def initialize(json)
@json = json
end
# Return the literal JSON to use
def to_json(*a)
@json
end
end
module ClassMethods
# The default opts to use when serializing model objects to JSON.
attr_reader :json_serializer_opts
# Create a new model object from the hash provided by parsing
# JSON. Handles column values (stored in +values+), associations
# (stored in +associations+), and other values (by calling a
# setter method). If an entry in the hash is not a column or
# an association, and no setter method exists, raises an Error.
def json_create(hash)
obj = new
cols = columns.map{|x| x.to_s}
assocs = associations.map{|x| x.to_s}
meths = obj.send(:setter_methods, nil, nil)
hash.delete(JSON.create_id)
hash.each do |k, v|
if assocs.include?(k)
obj.associations[k.to_sym] = v
elsif meths.include?("#{k}=")
obj.send("#{k}=", v)
elsif cols.include?(k)
obj.values[k.to_sym] = v
else
raise Error, "Entry in JSON hash not an association or column and no setter method exists: #{k}"
end
end
obj
end
# Call the dataset +to_json+ method.
def to_json(*a)
dataset.to_json(*a)
end
# Copy the current model object's default json options into the subclass.
def inherited(subclass)
super
opts = {}
json_serializer_opts.each{|k, v| opts[k] = (v.is_a?(Array) || v.is_a?(Hash)) ? v.dup : v}
subclass.instance_variable_set(:@json_serializer_opts, opts)
end
end
module InstanceMethods
# Parse the provided JSON, which should return a hash,
# and call +set+ with that hash.
def from_json(json)
set(JSON.parse(json))
end
# Return a string in JSON format. Accepts the following
# options:
#
# :except :: Symbol or Array of Symbols of columns not
# to include in the JSON output.
# :include :: Symbol, Array of Symbols, or a Hash with
# Symbol keys and Hash values specifying
# associations or other non-column attributes
# to include in the JSON output. Using a nested
# hash, you can pass options to associations
# to affect the JSON used for associated objects.
# :naked :: Not to add the JSON.create_id (json_class) key to the JSON
# output hash, so when the JSON is parsed, it
# will yield a hash instead of a model object.
# :only :: Symbol or Array of Symbols of columns to only
# include in the JSON output, ignoring all other
# columns.
# :root :: Qualify the JSON with the name of the object.
# Implies :naked since the object name is explicit.
def to_json(*a)
if opts = a.first.is_a?(Hash)
opts = model.json_serializer_opts.merge(a.first)
a = []
else
opts = model.json_serializer_opts
end
vals = values
cols = if only = opts[:only]
Array(only)
else
vals.keys - Array(opts[:except])
end
h = (JSON.create_id && !opts[:naked] && !opts[:root]) ? {JSON.create_id=>model.name} : {}
cols.each{|c| h[c.to_s] = send(c)}
if inc = opts[:include]
if inc.is_a?(Hash)
inc.each do |k, v|
v = v.empty? ? [] : [v]
h[k.to_s] = case objs = send(k)
when Array
objs.map{|obj| Literal.new(obj.to_json(*v))}
else
Literal.new(objs.to_json(*v))
end
end
else
Array(inc).each{|c| h[c.to_s] = send(c)}
end
end
h = {model.send(:underscore, model.to_s) => h} if opts[:root]
h.to_json(*a)
end
end
module DatasetMethods
# Return a JSON string representing an array of all objects in
# this dataset. Takes the same options as the the instance
# method, and passes them to every instance.
def to_json(*a)
if opts = a.first.is_a?(Hash)
opts = model.json_serializer_opts.merge(a.first)
a = []
else
opts = model.json_serializer_opts
end
res = row_proc ? all.map{|obj| Literal.new(obj.to_json(opts))} : all
opts[:root] ? {model.send(:pluralize, model.send(:underscore, model.to_s)) => res}.to_json(*a) : res.to_json(*a)
end
end
end
end
end
|