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   Sequel.parse_json(s)
391 rescue Sequel.json_parser_error_class => e
392   raise Sequel.convert_exception_class(e, Sequel::InvalidValue)
393 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
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_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
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
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
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
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