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, line 313 def self.db_parse_json(s) # SEQUEL6: Remove parse_json(s) rescue Sequel::InvalidValue raise unless s.is_a?(String) parse_json("[#{s}]").first end
Deprecated
# File lib/sequel/extensions/pg_json.rb, line 322 def self.db_parse_jsonb(s) # SEQUEL6: Remove parse_json(s, true) rescue Sequel::InvalidValue raise unless s.is_a?(String) parse_json("[#{s}]").first end
# File lib/sequel/extensions/pg_json.rb, line 235 def self.extended(db) db.instance_exec do add_conversion_proc(114, method(:_db_parse_json)) add_conversion_proc(3802, method(:_db_parse_jsonb)) if respond_to?(:register_array_type) register_array_type('json', :oid=>199, :scalar_oid=>114) register_array_type('jsonb', :oid=>3807, :scalar_oid=>3802) end @schema_type_classes[:json] = [JSONObject] @schema_type_classes[:jsonb] = [JSONBObject] end end
Return the wrapper class for the json type if value is a supported type.
# File lib/sequel/extensions/pg_json.rb, line 269 def self.json_primitive_wrapper(value) case value when ::Hash JSONHash when ::Array JSONArray when ::String JSONString when ::Integer JSONInteger when ::Float JSONFloat when ::NilClass JSONNull when ::TrueClass JSONTrue when ::FalseClass JSONFalse end end
Return the wrapper class for the jsonb type if value is a supported type.
# File lib/sequel/extensions/pg_json.rb, line 291 def self.jsonb_primitive_wrapper(value) case value when ::Hash JSONBHash when ::Array JSONBArray when ::String JSONBString when ::Integer JSONBInteger when ::Float JSONBFloat when ::NilClass JSONBNull when ::TrueClass JSONBTrue when ::FalseClass JSONBFalse end end
Deprecated
# File lib/sequel/extensions/pg_json.rb, line 331 def self.parse_json(s, jsonb=false) # SEQUEL6: Remove Sequel::Deprecation.deprecate("Sequel::Postgres::JSONDatabaseMethods.{parse_json,db_parse_json,db_parse_jsonb} are deprecated and will be removed in Sequel 6.") begin value = Sequel.parse_json(s) rescue Sequel.json_parser_error_class => e raise Sequel.convert_exception_class(e, Sequel::InvalidValue) end case value when Array (jsonb ? JSONBArray : JSONArray).new(value) when Hash (jsonb ? JSONBHash : JSONHash).new(value) when String, Numeric, true, false, nil value else raise Sequel::InvalidValue, "unhandled json value: #{value.inspect} (from #{s.inspect})" end end
Public Instance Methods
Handle json and jsonb types in bound variables
# File lib/sequel/extensions/pg_json.rb, line 365 def bound_variable_arg(arg, conn) case arg when JSONObject, JSONBObject Sequel.object_to_json(arg) else super end 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, line 379 def _db_parse_json(s) _wrap_json(_parse_json(s)) rescue Sequel::InvalidValue raise unless s.is_a?(String) _wrap_json(_parse_json("[#{s}]").first) end
Same as #_db_parse_json, but consider the input as jsonb.
# File lib/sequel/extensions/pg_json.rb, line 387 def _db_parse_jsonb(s) _wrap_jsonb(_parse_json(s)) rescue Sequel::InvalidValue raise unless s.is_a?(String) _wrap_jsonb(_parse_json("[#{s}]").first) 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, line 398 def _parse_json(s) Sequel.parse_json(s) rescue Sequel.json_parser_error_class => e raise Sequel.convert_exception_class(e, Sequel::InvalidValue) 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, line 406 def _wrap_json(value) if klass = JSONDatabaseMethods.json_wrapper(value) klass.new(value) elsif klass = JSONDatabaseMethods.json_primitive_wrapper(value) if wrap_json_primitives klass.new(value) else value end else raise Sequel::InvalidValue, "unhandled json value: #{value.inspect}" end 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, line 422 def _wrap_jsonb(value) if klass = JSONDatabaseMethods.jsonb_wrapper(value) klass.new(value) elsif klass = JSONDatabaseMethods.jsonb_primitive_wrapper(value) if wrap_json_primitives klass.new(value) else value end else raise Sequel::InvalidValue, "unhandled jsonb value: #{value.inspect}" end end
Make the column type detection recognize the json types.
# File lib/sequel/extensions/pg_json.rb, line 437 def schema_column_type(db_type) case db_type when 'json' :json when 'jsonb' :jsonb else super end 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, line 449 def schema_post_process(_) super.each do |a| h = a[1] if (h[:type] == :json || h[:type] == :jsonb) && h[:default] =~ /\A'(\{\}|\[\])'::jsonb?\z/ is_array = $1 == '[]' klass = if h[:type] == :json if is_array JSONArray else JSONHash end elsif is_array JSONBArray else JSONBHash end h[:callable_default] = lambda{klass.new(is_array ? [] : {})} end end end
Convert the value given to a JSON wrapper object.
# File lib/sequel/extensions/pg_json.rb, line 473 def typecast_value_json(value) case value when JSONObject value when String if typecast_json_strings JSONString.new(value) else _wrap_json(_parse_json(value)) end when *JSON_WRAP_CLASSES JSONDatabaseMethods.json_primitive_wrapper(value).new(value) when JSONBObject value = value.__getobj__ JSONDatabaseMethods.json_primitive_wrapper(value).new(value) else raise Sequel::InvalidValue, "invalid value for json: #{value.inspect}" end end
Convert the value given to a JSONB wrapper object.
# File lib/sequel/extensions/pg_json.rb, line 494 def typecast_value_jsonb(value) case value when JSONBObject value when String if typecast_json_strings JSONBString.new(value) else _wrap_jsonb(_parse_json(value)) end when *JSON_WRAP_CLASSES JSONDatabaseMethods.jsonb_primitive_wrapper(value).new(value) when JSONObject value = value.__getobj__ JSONDatabaseMethods.jsonb_primitive_wrapper(value).new(value) else raise Sequel::InvalidValue, "invalid value for jsonb: #{value.inspect}" end end