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
233 def self.db_parse_json(s)
234   # SEQUEL6: Remove
235   parse_json(s)
236 rescue Sequel::InvalidValue
237   raise unless s.is_a?(String)
238   parse_json("[#{s}]").first
239 end
db_parse_jsonb(s) click to toggle source

Deprecated

    # File lib/sequel/extensions/pg_json.rb
242 def self.db_parse_jsonb(s)
243   # SEQUEL6: Remove
244   parse_json(s, true)
245 rescue Sequel::InvalidValue
246   raise unless s.is_a?(String)
247   parse_json("[#{s}]").first
248 end
extended(db) click to toggle source
    # File lib/sequel/extensions/pg_json.rb
218 def self.extended(db)
219   db.instance_exec do
220     add_conversion_proc(114, method(:_db_parse_json))
221     add_conversion_proc(3802, method(:_db_parse_jsonb))
222     if respond_to?(:register_array_type)
223       register_array_type('json', :oid=>199, :scalar_oid=>114)
224       register_array_type('jsonb', :oid=>3807, :scalar_oid=>3802)
225     end
226     @schema_type_classes[:json] = [JSONObject]
227     @schema_type_classes[:jsonb] = [JSONBObject]
228   end
229 end
parse_json(s, jsonb=false) click to toggle source

Deprecated

    # File lib/sequel/extensions/pg_json.rb
251 def self.parse_json(s, jsonb=false)
252   # SEQUEL6: Remove
253   Sequel::Deprecation.deprecate("Sequel::Postgres::JSONDatabaseMethods.{parse_json,db_parse_json,db_parse_jsonb} are deprecated and will be removed in Sequel 6.")
254   begin
255     value = Sequel.parse_json(s)
256   rescue Sequel.json_parser_error_class => e
257     raise Sequel.convert_exception_class(e, Sequel::InvalidValue)
258   end
259 
260   case value
261   when Array
262     (jsonb ? JSONBArray : JSONArray).new(value)
263   when Hash 
264     (jsonb ? JSONBHash : JSONHash).new(value)
265   when String, Numeric, true, false, nil
266     value
267   else
268     raise Sequel::InvalidValue, "unhandled json value: #{value.inspect} (from #{s.inspect})"
269   end
270 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
285 def bound_variable_arg(arg, conn)
286   case arg
287   when JSONObject, JSONBObject
288     Sequel.object_to_json(arg)
289   else
290     super
291   end
292 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
299 def _db_parse_json(s)
300   _wrap_json(_parse_json(s))
301 rescue Sequel::InvalidValue
302   raise unless s.is_a?(String)
303   _wrap_json(_parse_json("[#{s}]").first)
304 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
307 def _db_parse_jsonb(s)
308   _wrap_jsonb(_parse_json(s))
309 rescue Sequel::InvalidValue
310   raise unless s.is_a?(String)
311   _wrap_jsonb(_parse_json("[#{s}]").first)
312 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
318 def _parse_json(s)
319   begin
320     Sequel.parse_json(s)
321   rescue Sequel.json_parser_error_class => e
322     raise Sequel.convert_exception_class(e, Sequel::InvalidValue)
323   end
324 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
328 def _wrap_json(value)
329   if klass = JSON_WRAPPER_MAPPING[value.class]
330     klass.new(value)
331   elsif klass = JSON_PRIMITIVE_WRAPPER_MAPPING[value.class]
332     if wrap_json_primitives
333       klass.new(value)
334     else
335       value
336     end
337   else
338     raise Sequel::InvalidValue, "unhandled json value: #{value.inspect}"
339   end
340 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
344 def _wrap_jsonb(value)
345   if klass = JSONB_WRAPPER_MAPPING[value.class]
346     klass.new(value)
347   elsif klass = JSONB_PRIMITIVE_WRAPPER_MAPPING[value.class]
348     if wrap_json_primitives
349       klass.new(value)
350     else
351       value
352     end
353   else
354     raise Sequel::InvalidValue, "unhandled jsonb value: #{value.inspect}"
355   end
356 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
359 def bound_variable_array(a)
360   case a
361   when JSONObject, JSONBObject
362     "\"#{Sequel.object_to_json(a).gsub('"', '\\"')}\""
363   else
364     super
365   end
366 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
369 def schema_column_type(db_type)
370   case db_type
371   when 'json'
372     :json
373   when 'jsonb'
374     :jsonb
375   else
376     super
377   end
378 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
381 def schema_post_process(_)
382   super.each do |a|
383     h = a[1]
384     if (h[:type] == :json || h[:type] == :jsonb) && h[:default] =~ /\A'(\{\}|\[\])'::jsonb?\z/
385       is_array = $1 == '[]'
386 
387       klass = if h[:type] == :json
388         if is_array
389           JSONArray
390         else
391           JSONHash
392         end
393       elsif is_array
394         JSONBArray
395       else
396         JSONBHash
397       end
398 
399       h[:callable_default] = lambda{klass.new(is_array ? [] : {})}
400     end
401   end
402 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
405 def typecast_value_json(value)
406   case value
407   when JSONObject
408     value
409   when String
410     if typecast_json_strings
411       JSONString.new(value)
412     else
413       _wrap_json(_parse_json(value))
414     end
415   when *JSON_WRAP_CLASSES
416     JSON_COMBINED_WRAPPER_MAPPING[value.class].new(value)
417   when JSONBObject
418     value = value.__getobj__
419     JSON_COMBINED_WRAPPER_MAPPING[value.class].new(value)
420   else
421     raise Sequel::InvalidValue, "invalid value for json: #{value.inspect}"
422   end
423 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
426 def typecast_value_jsonb(value)
427   case value
428   when JSONBObject
429     value
430   when String
431     if typecast_json_strings
432       JSONBString.new(value)
433     else
434       _wrap_jsonb(_parse_json(value))
435     end
436   when *JSONB_WRAP_CLASSES
437     JSONB_COMBINED_WRAPPER_MAPPING[value.class].new(value)
438   when JSONObject
439     value = value.__getobj__
440     JSONB_COMBINED_WRAPPER_MAPPING[value.class].new(value)
441   else
442     raise Sequel::InvalidValue, "invalid value for jsonb: #{value.inspect}"
443   end
444 end