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
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
db_parse_jsonb(s) click to toggle source

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
extended(db) click to toggle source
    # 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
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
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
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
240 def self.json_wrapper(value)
241   case value
242   when ::Hash
243     JSONHash
244   when ::Array
245     JSONArray
246   end
247 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
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
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
250 def self.jsonb_wrapper(value)
251   case value
252   when ::Hash
253     JSONBHash
254   when ::Array
255     JSONBArray
256   end
257 end
parse_json(s, jsonb=false) click to toggle source

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

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
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

_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
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
_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
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_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
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_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
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_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
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
bound_variable_array(a) click to toggle source

Handle json[] and jsonb[] types in bound variables.

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

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

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