module Sequel::Postgres::JSONDatabaseMethods

Methods enabling Database object integration with the json type.

Attributes

typecast_json_strings[RW]

Whether to typecast strings for json/jsonb types as JSON strings, instead of trying to parse the string as JSON. False by default.

wrap_json_primitives[RW]

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

db_parse_json(s) click to toggle source

Deprecated

    # File lib/sequel/extensions/pg_json.rb
314 def self.db_parse_json(s)
315   # SEQUEL6: Remove
316   parse_json(s)
317 rescue Sequel::InvalidValue
318   raise unless s.is_a?(String)
319   parse_json("[#{s}]").first
320 end
db_parse_jsonb(s) click to toggle source

Deprecated

    # File lib/sequel/extensions/pg_json.rb
323 def self.db_parse_jsonb(s)
324   # SEQUEL6: Remove
325   parse_json(s, true)
326 rescue Sequel::InvalidValue
327   raise unless s.is_a?(String)
328   parse_json("[#{s}]").first
329 end
extended(db) click to toggle source
    # File lib/sequel/extensions/pg_json.rb
236 def self.extended(db)
237   db.instance_exec do
238     add_conversion_proc(114, method(:_db_parse_json))
239     add_conversion_proc(3802, method(:_db_parse_jsonb))
240     if respond_to?(:register_array_type)
241       register_array_type('json', :oid=>199, :scalar_oid=>114)
242       register_array_type('jsonb', :oid=>3807, :scalar_oid=>3802)
243     end
244     @schema_type_classes[:json] = [JSONObject]
245     @schema_type_classes[:jsonb] = [JSONBObject]
246   end
247 end
json_primitive_wrapper(value) click to toggle source

Return the wrapper class for the json type if value is a supported type.

    # File lib/sequel/extensions/pg_json.rb
270 def self.json_primitive_wrapper(value)
271   case value
272   when ::Hash
273     JSONHash
274   when ::Array
275     JSONArray
276   when ::String
277     JSONString
278   when ::Integer
279     JSONInteger
280   when ::Float
281     JSONFloat
282   when ::NilClass
283     JSONNull
284   when ::TrueClass
285     JSONTrue
286   when ::FalseClass
287     JSONFalse
288   end
289 end
json_wrapper(value) click to toggle source

Return the wrapper class for the json type if value is Hash or Array.

    # File lib/sequel/extensions/pg_json.rb
250 def self.json_wrapper(value)
251   case value
252   when ::Hash
253     JSONHash
254   when ::Array
255     JSONArray
256   end
257 end
jsonb_primitive_wrapper(value) click to toggle source

Return the wrapper class for the jsonb type if value is a supported type.

    # File lib/sequel/extensions/pg_json.rb
292 def self.jsonb_primitive_wrapper(value)
293   case value
294   when ::Hash
295     JSONBHash
296   when ::Array
297     JSONBArray
298   when ::String
299     JSONBString
300   when ::Integer
301     JSONBInteger
302   when ::Float
303     JSONBFloat
304   when ::NilClass
305     JSONBNull
306   when ::TrueClass
307     JSONBTrue
308   when ::FalseClass
309     JSONBFalse
310   end
311 end
jsonb_wrapper(value) click to toggle source

Return the wrapper class for the jsonb type if value is Hash or Array.

    # File lib/sequel/extensions/pg_json.rb
260 def self.jsonb_wrapper(value)
261   case value
262   when ::Hash
263     JSONBHash
264   when ::Array
265     JSONBArray
266   end
267 end
parse_json(s, jsonb=false) click to toggle source

Deprecated

    # File lib/sequel/extensions/pg_json.rb
332 def self.parse_json(s, jsonb=false)
333   # SEQUEL6: Remove
334   Sequel::Deprecation.deprecate("Sequel::Postgres::JSONDatabaseMethods.{parse_json,db_parse_json,db_parse_jsonb} are deprecated and will be removed in Sequel 6.")
335   begin
336     value = Sequel.parse_json(s)
337   rescue Sequel.json_parser_error_class => e
338     raise Sequel.convert_exception_class(e, Sequel::InvalidValue)
339   end
340 
341   case value
342   when Array
343     (jsonb ? JSONBArray : JSONArray).new(value)
344   when Hash 
345     (jsonb ? JSONBHash : JSONHash).new(value)
346   when String, Numeric, true, false, nil
347     value
348   else
349     raise Sequel::InvalidValue, "unhandled json value: #{value.inspect} (from #{s.inspect})"
350   end
351 end

Public Instance Methods

bound_variable_arg(arg, conn) click to toggle source

Handle json and jsonb types in bound variables

Calls superclass method
    # File lib/sequel/extensions/pg_json.rb
366 def bound_variable_arg(arg, conn)
367   case arg
368   when JSONObject, JSONBObject
369     Sequel.object_to_json(arg)
370   else
371     super
372   end
373 end

Private Instance Methods

_db_parse_json(s) click to toggle source

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
380 def _db_parse_json(s)
381   _wrap_json(_parse_json(s))
382 rescue Sequel::InvalidValue
383   raise unless s.is_a?(String)
384   _wrap_json(_parse_json("[#{s}]").first)
385 end
_db_parse_jsonb(s) click to toggle source

Same as _db_parse_json, but consider the input as jsonb.

    # File lib/sequel/extensions/pg_json.rb
388 def _db_parse_jsonb(s)
389   _wrap_jsonb(_parse_json(s))
390 rescue Sequel::InvalidValue
391   raise unless s.is_a?(String)
392   _wrap_jsonb(_parse_json("[#{s}]").first)
393 end
_parse_json(s) click to toggle source

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
399 def _parse_json(s)
400   Sequel.parse_json(s)
401 rescue Sequel.json_parser_error_class => e
402   raise Sequel.convert_exception_class(e, Sequel::InvalidValue)
403 end
_wrap_json(value) click to toggle source

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
407 def _wrap_json(value)
408   if klass = JSONDatabaseMethods.json_wrapper(value)
409     klass.new(value)
410   elsif klass = JSONDatabaseMethods.json_primitive_wrapper(value)
411     if wrap_json_primitives
412       klass.new(value)
413     else
414       value
415     end
416   else
417     raise Sequel::InvalidValue, "unhandled json value: #{value.inspect}"
418   end
419 end
_wrap_jsonb(value) click to toggle source

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
423 def _wrap_jsonb(value)
424   if klass = JSONDatabaseMethods.jsonb_wrapper(value)
425     klass.new(value)
426   elsif klass = JSONDatabaseMethods.jsonb_primitive_wrapper(value)
427     if wrap_json_primitives
428       klass.new(value)
429     else
430       value
431     end
432   else
433     raise Sequel::InvalidValue, "unhandled jsonb value: #{value.inspect}"
434   end
435 end
schema_column_type(db_type) click to toggle source

Make the column type detection recognize the json types.

Calls superclass method
    # 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
schema_post_process(_) click to toggle source

Set the :callable_default value if the default value is recognized as an empty json/jsonb array/hash.

Calls superclass method
    # 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
typecast_value_json(value) click to toggle source

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
typecast_value_jsonb(value) click to toggle source

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