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 304 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 313 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 226 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 260 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 282 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 322 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 356 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 370 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 378 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 389 def _parse_json(s) begin Sequel.parse_json(s) rescue Sequel.json_parser_error_class => e raise Sequel.convert_exception_class(e, Sequel::InvalidValue) end 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 399 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 415 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
Handle json[] and jsonb[] types in bound variables.
# File lib/sequel/extensions/pg_json.rb, line 430 def bound_variable_array(a) case a when JSONObject, JSONBObject "\"#{Sequel.object_to_json(a).gsub('"', '\\"')}\"" else super end end
Make the column type detection recognize the json types.
# File lib/sequel/extensions/pg_json.rb, line 440 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 452 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 476 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 497 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