Class: Object

Inherits:
BasicObject
Defined in:
lib/safe_object_as_json.rb

Instance Method Summary collapse

Instance Method Details

#as_json(options = nil) ⇒ Object

Converts any object to JSON by creating a hash out of its instance variables. If there is a circular reference within an object hierarchy, then the duplicate reference will be omitted in order to avoid infinite recursion.

Parameters:

  • options (Hash) (defaults to: nil)

Returns:



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/safe_object_as_json.rb', line 43

def as_json(options = nil)
  SafeObjectAsJson.track_references do |references|
    if respond_to?(:to_hash)
      # Register this object while its hash representation is being serialized so a
      # circular reference back to it serializes as nil instead of recursing forever.
      # A distinct key is used so that the registration of this object's id by a
      # caller serializing it as a value is not mistaken for a circular reference.
      if references.add?([:to_hash, object_id])
        begin
          to_hash.as_json(options)
        ensure
          references.delete([:to_hash, object_id])
        end
      end
    else
      # The default as_json serializer serializes the instance variables as name value
      # pairs. In order to prevent infinite recursion, we keep track of the objects
      # already being serialized and omit them if they are referenced recursively.
      added = references.add?(object_id)
      begin
        hash = {}

        # Apply :only and :except filter from the options to the hash of instance variables.
        values = instance_values
        if options && SafeObjectAsJson::SUPPORT_FILTERING
          only_attr = options[:only]
          if only_attr
            values = values.slice(*Array(only_attr).map(&:to_s))
          else
            except_attr = options[:except]
            if except_attr
              values = values.except(*Array(except_attr).map(&:to_s))
            end
          end
        end

        values.each do |name, value|
          next if references.include?(value.object_id) || value.is_a?(Proc) || value.is_a?(IO)

          references << value.object_id
          begin
            hash[name] = (options.nil? ? value.as_json : value.as_json(options.dup))
          ensure
            references.delete(value.object_id)
          end
        end
        hash
      ensure
        references.delete(object_id) if added
      end
    end
  end
end