module Sequel::Postgres::JSONDatabaseMethods
Methods enabling Database
object integration with the json type.
Attributes
Whether to typecast strings for json/jsonb types as JSON strings, instead of trying to parse the string as JSON. False by default.
Whether to wrap JSON primitives instead of using Ruby objects. Wrapping the primitives allows the primitive values to roundtrip, but it can cause problems, especially as false/null JSON values will be treated as truthy in Ruby due to the wrapping. False by default.
Public Class Methods
Deprecated
# File lib/sequel/extensions/pg_json.rb 304 def self.db_parse_json(s) 305 # SEQUEL6: Remove 306 parse_json(s) 307 rescue Sequel::InvalidValue 308 raise unless s.is_a?(String) 309 parse_json("[#{s}]").first 310 end
Deprecated
# File lib/sequel/extensions/pg_json.rb 313 def self.db_parse_jsonb(s) 314 # SEQUEL6: Remove 315 parse_json(s, true) 316 rescue Sequel::InvalidValue 317 raise unless s.is_a?(String) 318 parse_json("[#{s}]").first 319 end
# File lib/sequel/extensions/pg_json.rb 226 def self.extended(db) 227 db.instance_exec do 228 add_conversion_proc(114, method(:_db_parse_json)) 229 add_conversion_proc(3802, method(:_db_parse_jsonb)) 230 if respond_to?(:register_array_type) 231 register_array_type('json', :oid=>199, :scalar_oid=>114) 232 register_array_type('jsonb', :oid=>3807, :scalar_oid=>3802) 233 end 234 @schema_type_classes[:json] = [JSONObject] 235 @schema_type_classes[:jsonb] = [JSONBObject] 236 end 237 end
Return the wrapper class for the json type if value is a supported type.
# File lib/sequel/extensions/pg_json.rb 260 def self.json_primitive_wrapper(value) 261 case value 262 when ::Hash 263 JSONHash 264 when ::Array 265 JSONArray 266 when ::String 267 JSONString 268 when ::Integer 269 JSONInteger 270 when ::Float 271 JSONFloat 272 when ::NilClass 273 JSONNull 274 when ::TrueClass 275 JSONTrue 276 when ::FalseClass 277 JSONFalse 278 end 279 end
Return the wrapper class for the jsonb type if value is a supported type.
# File lib/sequel/extensions/pg_json.rb 282 def self.jsonb_primitive_wrapper(value) 283 case value 284 when ::Hash 285 JSONBHash 286 when ::Array 287 JSONBArray 288 when ::String 289 JSONBString 290 when ::Integer 291 JSONBInteger 292 when ::Float 293 JSONBFloat 294 when ::NilClass 295 JSONBNull 296 when ::TrueClass 297 JSONBTrue 298 when ::FalseClass 299 JSONBFalse 300 end 301 end
Deprecated
# File lib/sequel/extensions/pg_json.rb 322 def self.parse_json(s, jsonb=false) 323 # SEQUEL6: Remove 324 Sequel::Deprecation.deprecate("Sequel::Postgres::JSONDatabaseMethods.{parse_json,db_parse_json,db_parse_jsonb} are deprecated and will be removed in Sequel 6.") 325 begin 326 value = Sequel.parse_json(s) 327 rescue Sequel.json_parser_error_class => e 328 raise Sequel.convert_exception_class(e, Sequel::InvalidValue) 329 end 330 331 case value 332 when Array 333 (jsonb ? JSONBArray : JSONArray).new(value) 334 when Hash 335 (jsonb ? JSONBHash : JSONHash).new(value) 336 when String, Numeric, true, false, nil 337 value 338 else 339 raise Sequel::InvalidValue, "unhandled json value: #{value.inspect} (from #{s.inspect})" 340 end 341 end
Public Instance Methods
Handle json and jsonb types in bound variables
# File lib/sequel/extensions/pg_json.rb 356 def bound_variable_arg(arg, conn) 357 case arg 358 when JSONObject, JSONBObject 359 Sequel.object_to_json(arg) 360 else 361 super 362 end 363 end
Private Instance 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 370 def _db_parse_json(s) 371 _wrap_json(_parse_json(s)) 372 rescue Sequel::InvalidValue 373 raise unless s.is_a?(String) 374 _wrap_json(_parse_json("[#{s}]").first) 375 end
Same as _db_parse_json
, but consider the input as jsonb.
# File lib/sequel/extensions/pg_json.rb 378 def _db_parse_jsonb(s) 379 _wrap_jsonb(_parse_json(s)) 380 rescue Sequel::InvalidValue 381 raise unless s.is_a?(String) 382 _wrap_jsonb(_parse_json("[#{s}]").first) 383 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 389 def _parse_json(s) 390 begin 391 Sequel.parse_json(s) 392 rescue Sequel.json_parser_error_class => e 393 raise Sequel.convert_exception_class(e, Sequel::InvalidValue) 394 end 395 end
Wrap the parsed JSON value in the appropriate JSON wrapper class. Only wrap primitive values if wrap_json_primitives
is set.
# File lib/sequel/extensions/pg_json.rb 399 def _wrap_json(value) 400 if klass = JSONDatabaseMethods.json_wrapper(value) 401 klass.new(value) 402 elsif klass = JSONDatabaseMethods.json_primitive_wrapper(value) 403 if wrap_json_primitives 404 klass.new(value) 405 else 406 value 407 end 408 else 409 raise Sequel::InvalidValue, "unhandled json value: #{value.inspect}" 410 end 411 end
Wrap the parsed JSON value in the appropriate JSONB wrapper class. Only wrap primitive values if wrap_json_primitives
is set.
# File lib/sequel/extensions/pg_json.rb 415 def _wrap_jsonb(value) 416 if klass = JSONDatabaseMethods.jsonb_wrapper(value) 417 klass.new(value) 418 elsif klass = JSONDatabaseMethods.jsonb_primitive_wrapper(value) 419 if wrap_json_primitives 420 klass.new(value) 421 else 422 value 423 end 424 else 425 raise Sequel::InvalidValue, "unhandled jsonb value: #{value.inspect}" 426 end 427 end
Handle json[] and jsonb[] types in bound variables.
# File lib/sequel/extensions/pg_json.rb 430 def bound_variable_array(a) 431 case a 432 when JSONObject, JSONBObject 433 "\"#{Sequel.object_to_json(a).gsub('"', '\\"')}\"" 434 else 435 super 436 end 437 end
Make the column type detection recognize the json types.
# File lib/sequel/extensions/pg_json.rb 440 def schema_column_type(db_type) 441 case db_type 442 when 'json' 443 :json 444 when 'jsonb' 445 :jsonb 446 else 447 super 448 end 449 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 452 def schema_post_process(_) 453 super.each do |a| 454 h = a[1] 455 if (h[:type] == :json || h[:type] == :jsonb) && h[:default] =~ /\A'(\{\}|\[\])'::jsonb?\z/ 456 is_array = $1 == '[]' 457 458 klass = if h[:type] == :json 459 if is_array 460 JSONArray 461 else 462 JSONHash 463 end 464 elsif is_array 465 JSONBArray 466 else 467 JSONBHash 468 end 469 470 h[:callable_default] = lambda{klass.new(is_array ? [] : {})} 471 end 472 end 473 end
Convert the value given to a JSON wrapper object.
# File lib/sequel/extensions/pg_json.rb 476 def typecast_value_json(value) 477 case value 478 when JSONObject 479 value 480 when String 481 if typecast_json_strings 482 JSONString.new(value) 483 else 484 _wrap_json(_parse_json(value)) 485 end 486 when *JSON_WRAP_CLASSES 487 JSONDatabaseMethods.json_primitive_wrapper(value).new(value) 488 when JSONBObject 489 value = value.__getobj__ 490 JSONDatabaseMethods.json_primitive_wrapper(value).new(value) 491 else 492 raise Sequel::InvalidValue, "invalid value for json: #{value.inspect}" 493 end 494 end
Convert the value given to a JSONB wrapper object.
# File lib/sequel/extensions/pg_json.rb 497 def typecast_value_jsonb(value) 498 case value 499 when JSONBObject 500 value 501 when String 502 if typecast_json_strings 503 JSONBString.new(value) 504 else 505 _wrap_jsonb(_parse_json(value)) 506 end 507 when *JSON_WRAP_CLASSES 508 JSONDatabaseMethods.jsonb_primitive_wrapper(value).new(value) 509 when JSONObject 510 value = value.__getobj__ 511 JSONDatabaseMethods.jsonb_primitive_wrapper(value).new(value) 512 else 513 raise Sequel::InvalidValue, "invalid value for jsonb: #{value.inspect}" 514 end 515 end