module Sequel::Postgres::JSONDatabaseMethods
Methods enabling Database
object integration with the json type.
Public Class Methods
Parse JSON data coming from the database. Since PostgreSQL allows non JSON data in JSON fields (such as plain numbers and strings), we don't want to raise an exception for that.
# File lib/sequel/extensions/pg_json.rb 145 def self.db_parse_json(s) 146 parse_json(s) 147 rescue Sequel::InvalidValue 148 raise unless s.is_a?(String) 149 parse_json("[#{s}]").first 150 end
Same as db_parse_json
, but consider the input as jsonb.
# File lib/sequel/extensions/pg_json.rb 153 def self.db_parse_jsonb(s) 154 parse_json(s, true) 155 rescue Sequel::InvalidValue 156 raise unless s.is_a?(String) 157 parse_json("[#{s}]").first 158 end
# File lib/sequel/extensions/pg_json.rb 129 def self.extended(db) 130 db.instance_exec do 131 add_conversion_proc(114, JSONDatabaseMethods.method(:db_parse_json)) 132 add_conversion_proc(3802, JSONDatabaseMethods.method(:db_parse_jsonb)) 133 if respond_to?(:register_array_type) 134 register_array_type('json', :oid=>199, :scalar_oid=>114) 135 register_array_type('jsonb', :oid=>3807, :scalar_oid=>3802) 136 end 137 @schema_type_classes[:json] = [JSONHash, JSONArray] 138 @schema_type_classes[:jsonb] = [JSONBHash, JSONBArray] 139 end 140 end
Parse the given string as json, returning either a JSONArray
or JSONHash
instance (or JSONBArray
or JSONBHash
instance if jsonb argument is true), or a String
, Numeric
, true, false, or nil if the json library used supports that.
# File lib/sequel/extensions/pg_json.rb 164 def self.parse_json(s, jsonb=false) 165 begin 166 value = Sequel.parse_json(s) 167 rescue Sequel.json_parser_error_class => e 168 raise Sequel.convert_exception_class(e, Sequel::InvalidValue) 169 end 170 171 case value 172 when Array 173 (jsonb ? JSONBArray : JSONArray).new(value) 174 when Hash 175 (jsonb ? JSONBHash : JSONHash).new(value) 176 when String, Numeric, true, false, nil 177 value 178 else 179 raise Sequel::InvalidValue, "unhandled json value: #{value.inspect} (from #{s.inspect})" 180 end 181 end
Public Instance Methods
Handle json and jsonb types in bound variables
# File lib/sequel/extensions/pg_json.rb 184 def bound_variable_arg(arg, conn) 185 case arg 186 when JSONArrayBase, JSONHashBase 187 Sequel.object_to_json(arg) 188 else 189 super 190 end 191 end
Private Instance Methods
Handle json[] and jsonb[] types in bound variables.
# File lib/sequel/extensions/pg_json.rb 196 def bound_variable_array(a) 197 case a 198 when JSONHashBase, JSONArrayBase 199 "\"#{Sequel.object_to_json(a).gsub('"', '\\"')}\"" 200 else 201 super 202 end 203 end
Make the column type detection recognize the json types.
# File lib/sequel/extensions/pg_json.rb 206 def schema_column_type(db_type) 207 case db_type 208 when 'json' 209 :json 210 when 'jsonb' 211 :jsonb 212 else 213 super 214 end 215 end
Set the :callable_default value if the default value is recognized as an empty json/jsonb array/hash.
# File lib/sequel/extensions/pg_json.rb 218 def schema_post_process(_) 219 super.each do |a| 220 h = a[1] 221 if (h[:type] == :json || h[:type] == :jsonb) && h[:default] =~ /\A'(\{\}|\[\])'::jsonb?\z/ 222 is_array = $1 == '[]' 223 224 klass = if h[:type] == :json 225 if is_array 226 JSONArray 227 else 228 JSONHash 229 end 230 elsif is_array 231 JSONBArray 232 else 233 JSONBHash 234 end 235 236 h[:callable_default] = lambda{klass.new(is_array ? [] : {})} 237 end 238 end 239 end
Convert the value given to a JSONArray
or JSONHash
# File lib/sequel/extensions/pg_json.rb 242 def typecast_value_json(value) 243 case value 244 when JSONArray, JSONHash 245 value 246 when Array 247 JSONArray.new(value) 248 when Hash 249 JSONHash.new(value) 250 when JSONBArray 251 JSONArray.new(value.to_a) 252 when JSONBHash 253 JSONHash.new(value.to_hash) 254 when String 255 JSONDatabaseMethods.parse_json(value) 256 else 257 raise Sequel::InvalidValue, "invalid value for json: #{value.inspect}" 258 end 259 end
Convert the value given to a JSONBArray
or JSONBHash
# File lib/sequel/extensions/pg_json.rb 262 def typecast_value_jsonb(value) 263 case value 264 when JSONBArray, JSONBHash 265 value 266 when Array 267 JSONBArray.new(value) 268 when Hash 269 JSONBHash.new(value) 270 when JSONArray 271 JSONBArray.new(value.to_a) 272 when JSONHash 273 JSONBHash.new(value.to_hash) 274 when String 275 JSONDatabaseMethods.parse_json(value, true) 276 else 277 raise Sequel::InvalidValue, "invalid value for jsonb: #{value.inspect}" 278 end 279 end