Repository: rails/rails
File: activesupport/lib/active_support/json/encoding.rb (Ruby)

Code before:
              result
            when Array
              value.map { |v| jsonify(v) }
            else
              if defined?(::JSON::Fragment) && ::JSON::Fragment === value
                value
              else
                jsonify value.as_json
              end
            end
          end

          # Encode a "jsonified" Ruby data structure using the JSON gem
          def stringify(jsonified)
            ::JSON.generate(jsonified)
          end
      end

      # ruby/json 2.14.x yields non-String keys but doesn't let us know it's a key
      if defined?(::JSON::Coder) && Gem::Version.new(::JSON::VERSION) >= Gem::Version.new("2.15.2")
        class JSONGemCoderEncoder # :nodoc:
          JSON_NATIVE_TYPES = [Hash, Array, Float, String, Symbol, Integer, NilClass, TrueClass, FalseClass, ::JSON::Fragment].freeze
          CODER = ::JSON::Coder.new do |value, is_key|
            json_value = value.as_json
            # Keep compatibility by calling to_s on non-String keys
            next value.to_s if is_key
            # Handle objects returning self from as_json
            if json_value.equal?(value)
              next ::JSON::Fragment.new(::JSON.generate(json_value))
            end
            # Handle objects not returning JSON-native types from as_json
            count = 5
            until JSON_NATIVE_TYPES.include?(json_value.class)
              raise SystemStackError if count == 0
              json_value = json_value.as_json
              count -= 1
            end
            json_value
          end


          def initialize(options = nil)
            if options
              options = options.dup
              @escape = options.delete(:escape) { true }
              @options = options.freeze
            else
              @escape = true
              @options = {}.freeze
            end
          end

Review comment (suggestion):
If we're going to return `value.to_s` we can skip calling `value.as_json`, but I think we should use `as_json` if it's a string.

Code after:
              result
            when Array
              value.map { |v| jsonify(v) }
            else
              if defined?(::JSON::Fragment) && ::JSON::Fragment === value
                value
              else
                jsonify value.as_json
              end
            end
          end

          # Encode a "jsonified" Ruby data structure using the JSON gem
          def stringify(jsonified)
            ::JSON.generate(jsonified)
          end
      end

      # ruby/json 2.14.x yields non-String keys but doesn't let us know it's a key
      if defined?(::JSON::Coder) && Gem::Version.new(::JSON::VERSION) >= Gem::Version.new("2.15.2")
        class JSONGemCoderEncoder # :nodoc:
          JSON_NATIVE_TYPES = [Hash, Array, Float, String, Symbol, Integer, NilClass, TrueClass, FalseClass, ::JSON::Fragment].freeze
          CODER = ::JSON::Coder.new do |value, is_key|
            json_value = value.as_json

            # Keep compatibility by calling to_s on non-String keys
            next value.to_s if is_key && !(String === json_value)

            # Handle objects returning self from as_json
            if json_value.equal?(value)
              next ::JSON::Fragment.new(::JSON.generate(json_value))
            end
            # Handle objects not returning JSON-native types from as_json
            count = 5
            until JSON_NATIVE_TYPES.include?(json_value.class)
              raise SystemStackError if count == 0
              json_value = json_value.as_json
              count -= 1
            end
            json_value
          end


          def initialize(options = nil)
            if options
              options = options.dup
              @escape = options.delete(:escape) { true }
              @options = options.freeze
            else
              @escape = true
              @options = {}.freeze