Module: Tins::HashSymbolizeKeysRecursive

Extended by:
ThreadLocal
Defined in:
lib/tins/hash_symbolize_keys_recursive.rb

Overview

This module provides recursive symbolization of hash keys. It handles nested structures including hashes and arrays, with special handling for circular references to prevent infinite recursion.

Examples:

Basic usage

hash = { "name" => "John", "address" => { "street" => "123 Main St" } }
hash.symbolize_keys_recursive
# => { name: "John", address: { street: "123 Main St" } }

Handling circular references

hash = { "name" => "John" }
hash["self"] = hash  # Circular reference
hash.symbolize_keys_recursive(circular: "[Circular Reference]")
# => { name: "John", self: "[Circular Reference]" }

Instance Method Summary collapse

Methods included from ThreadLocal

instance_thread_local, thread_local

Instance Method Details

#_transform_keys_recursive(object, circular: nil, transform:) ⇒ Object (private)

Performs the actual recursive transformation work

Parameters:

  • object (Object)

    The object to process

  • circular (Object) (defaults to: nil)

    The value to return for circular references

  • transform (Symbol)

    The transformation to apply to keys (:to_sym or :to_s).

Returns:

  • (Object)

    The processed object with transformed keys



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/tins/hash_symbolize_keys_recursive.rb', line 110

def _transform_keys_recursive(object, circular: nil, transform:)
  case
  when seen[object.__id__]
    object = circular
  when object.respond_to?(:to_hash)
    object = object.to_hash
    seen[object.__id__] = true
    new_object = object.class.new
    seen[new_object.__id__] = true
    object.each do |k, v|
      new_object[k.to_s.__send__(transform)] =
        _transform_keys_recursive(v, circular: circular, transform:)
    end
    object = new_object
  when object.respond_to?(:to_ary)
    object = object.to_ary
    seen[object.__id__] = true
    new_object = object.class.new(object.size)
    seen[new_object.__id__] = true
    object.each_with_index do |v, i|
      new_object[i] = _transform_keys_recursive(v, circular: circular, transform:)
    end
    object = new_object
  end
  object
end

#stringify_keys_recursive(circular: nil) ⇒ Hash

Converts all keys in the hash (and nested hashes) to strings.

Examples:

hash = { name: "John", address: { city: "NYC" } }
hash.stringify_keys_recursive
# => { "name" => "John", "address" => { "city" => "NYC" } }

Parameters:

  • circular (Object) (defaults to: nil)

    The value to return for circular references.

Returns:

  • (Hash)

    A new hash with all keys converted to strings.



66
67
68
69
70
71
# File 'lib/tins/hash_symbolize_keys_recursive.rb', line 66

def stringify_keys_recursive(circular: nil)
  self.seen = {}
  _transform_keys_recursive(self, circular: circular, transform: :to_s)
ensure
  self.seen = nil
end

#stringify_keys_recursive!(circular: nil) ⇒ Hash

Converts all keys in the hash (and nested hashes) to strings in place.

Examples:

hash = { name: "John", address: { city: "NYC" } }
hash.stringify_keys_recursive!
# => { "name" => "John", "address" => { "city" => "NYC" } }

Parameters:

  • circular (Object) (defaults to: nil)

    The value to return for circular references.

Returns:

  • (Hash)

    The same hash with all keys converted to strings.



98
99
100
# File 'lib/tins/hash_symbolize_keys_recursive.rb', line 98

def stringify_keys_recursive!(circular: nil)
  replace stringify_keys_recursive(circular: circular)
end

#symbolize_keys_recursive(circular: nil) ⇒ Hash, ...

Recursively converts all string keys in a hash (and nested hashes/arrays) to symbols. This method does not modify the original hash.

Examples:

Basic usage

{ "name" => "John", "age" => 30 }.symbolize_keys_recursive
# => { name: "John", age: 30 }

Nested structures

{
  "user" => {
    "name" => "John",
    "hobbies" => ["reading", "swimming"]
  }
}.symbolize_keys_recursive
# => { user: { name: "John", hobbies: ["reading", "swimming"] } }

Circular reference handling

hash = { "name" => "John" }
hash["self"] = hash
hash.symbolize_keys_recursive(circular: "[Circular]")
# => { name: "John", self: "[Circular]" }

Parameters:

  • circular (Object) (defaults to: nil)

    The value to use when encountering circular references. Defaults to nil, which means circular references will be ignored.

Returns:



50
51
52
53
54
55
# File 'lib/tins/hash_symbolize_keys_recursive.rb', line 50

def symbolize_keys_recursive(circular: nil)
  self.seen = {}
  _transform_keys_recursive(self, circular: circular, transform: :to_sym)
ensure
  self.seen = nil
end

#symbolize_keys_recursive!(circular: nil) ⇒ Hash, ...

Recursively converts all string keys in a hash (and nested hashes/arrays) to symbols. This method modifies the original hash in place.

Examples:

Basic usage

hash = { "name" => "John", "age" => 30 }
hash.symbolize_keys_recursive!
# => { name: "John", age: 30 }
# hash is now modified in place

Parameters:

  • circular (Object) (defaults to: nil)

    The value to use when encountering circular references. Defaults to nil, which means circular references will be ignored.

Returns:



85
86
87
# File 'lib/tins/hash_symbolize_keys_recursive.rb', line 85

def symbolize_keys_recursive!(circular: nil)
  replace symbolize_keys_recursive(circular: circular)
end