module JSON::TruffleRuby::Generator::GeneratorMethods::Hash

Public Instance Methods

to_json(state = nil, *) click to toggle source

Returns a JSON string containing a JSON object, that is unparsed from this Hash instance. state is a JSON::State object, that can also be used to configure the produced JSON string output further. depth is used to find out nesting depth, to indent accordingly.

# File lib/json/truffle_ruby/generator.rb, line 482
def to_json(state = nil, *)
  state = State.from_state(state)
  state.check_max_nesting
  json_transform(state)
end

Private Instance Methods

json_shift(state) click to toggle source
# File lib/json/truffle_ruby/generator.rb, line 490
def json_shift(state)
  state.object_nl.empty? or return ''
  state.indent * state.depth
end
json_transform(state) click to toggle source
# File lib/json/truffle_ruby/generator.rb, line 495
def json_transform(state)
  depth = state.depth += 1

  if empty?
    state.depth -= 1
    return '{}'
  end

  delim = ",#{state.object_nl}"
  result = +"{#{state.object_nl}"
  first = true
  key_type = nil
  indent = !state.object_nl.empty?
  each { |key, value|
    if first
      key_type = key.class
    else
      if key_type && !state.allow_duplicate_key? && key_type != key.class
        key_type = nil # stop checking
        JSON.send(:on_mixed_keys_hash, self, state.allow_duplicate_key? == false)
      end
      result << delim
    end
    result << state.indent * depth if indent

    if state.strict? && !Generator.native_key?(key)
      if state.as_json
        key = state.as_json.call(key, true)
      end

      unless Generator.native_key?(key)
        raise GeneratorError.new("#{key.class} not allowed as object key in JSON", value)
      end
    end

    key_str = key.to_s
    if key_str.is_a?(String)
      key_json = key_str.to_json(state)
    else
      raise TypeError, "#{key.class}#to_s returns an instance of #{key_str.class}, expected a String"
    end

    result = +"#{result}#{key_json}#{state.space_before}:#{state.space}"
    if state.strict? && !Generator.native_type?(value)
      if state.as_json
        value = state.as_json.call(value, false)
        unless Generator.native_type?(value)
          raise GeneratorError.new("#{value.class} returned by #{state.as_json} not allowed in JSON", value)
        end
        result << value.to_json(state)
      else
        raise GeneratorError.new("#{value.class} not allowed in JSON", value)
      end
    elsif value.respond_to?(:to_json)
      result << value.to_json(state)
    else
      result << %{"#{String(value)}"}
    end
    first = false
  }
  depth = state.depth -= 1
  unless first
    result << state.object_nl
    result << state.indent * depth if indent
  end
  result << '}'
  result
end