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 Sequel.parse_json(s) 391 rescue Sequel.json_parser_error_class => e 392 raise Sequel.convert_exception_class(e, Sequel::InvalidValue) 393 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 397 def _wrap_json(value) 398 if klass = JSONDatabaseMethods.json_wrapper(value) 399 klass.new(value) 400 elsif klass = JSONDatabaseMethods.json_primitive_wrapper(value) 401 if wrap_json_primitives 402 klass.new(value) 403 else 404 value 405 end 406 else 407 raise Sequel::InvalidValue, "unhandled json value: #{value.inspect}" 408 end 409 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 413 def _wrap_jsonb(value) 414 if klass = JSONDatabaseMethods.jsonb_wrapper(value) 415 klass.new(value) 416 elsif klass = JSONDatabaseMethods.jsonb_primitive_wrapper(value) 417 if wrap_json_primitives 418 klass.new(value) 419 else 420 value 421 end 422 else 423 raise Sequel::InvalidValue, "unhandled jsonb value: #{value.inspect}" 424 end 425 end
Handle json[] and jsonb[] types in bound variables.
# File lib/sequel/extensions/pg_json.rb 428 def bound_variable_array(a) 429 case a 430 when JSONObject, JSONBObject 431 "\"#{Sequel.object_to_json(a).gsub('"', '\\"')}\"" 432 else 433 super 434 end 435 end
Make the column type detection recognize the json types.
# File lib/sequel/extensions/pg_json.rb 438 def schema_column_type(db_type) 439 case db_type 440 when 'json' 441 :json 442 when 'jsonb' 443 :jsonb 444 else 445 super 446 end 447 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 450 def schema_post_process(_) 451 super.each do |a| 452 h = a[1] 453 if (h[:type] == :json || h[:type] == :jsonb) && h[:default] =~ /\A'(\{\}|\[\])'::jsonb?\z/ 454 is_array = $1 == '[]' 455 456 klass = if h[:type] == :json 457 if is_array 458 JSONArray 459 else 460 JSONHash 461 end 462 elsif is_array 463 JSONBArray 464 else 465 JSONBHash 466 end 467 468 h[:callable_default] = lambda{klass.new(is_array ? [] : {})} 469 end 470 end 471 end
Convert the value given to a JSON wrapper object.
# File lib/sequel/extensions/pg_json.rb 474 def typecast_value_json(value) 475 case value 476 when JSONObject 477 value 478 when String 479 if typecast_json_strings 480 JSONString.new(value) 481 else 482 _wrap_json(_parse_json(value)) 483 end 484 when *JSON_WRAP_CLASSES 485 JSONDatabaseMethods.json_primitive_wrapper(value).new(value) 486 when JSONBObject 487 value = value.__getobj__ 488 JSONDatabaseMethods.json_primitive_wrapper(value).new(value) 489 else 490 raise Sequel::InvalidValue, "invalid value for json: #{value.inspect}" 491 end 492 end
Convert the value given to a JSONB wrapper object.
# File lib/sequel/extensions/pg_json.rb 495 def typecast_value_jsonb(value) 496 case value 497 when JSONBObject 498 value 499 when String 500 if typecast_json_strings 501 JSONBString.new(value) 502 else 503 _wrap_jsonb(_parse_json(value)) 504 end 505 when *JSON_WRAP_CLASSES 506 JSONDatabaseMethods.jsonb_primitive_wrapper(value).new(value) 507 when JSONObject 508 value = value.__getobj__ 509 JSONDatabaseMethods.jsonb_primitive_wrapper(value).new(value) 510 else 511 raise Sequel::InvalidValue, "invalid value for jsonb: #{value.inspect}" 512 end 513 end