Class: SmarterJSON::Generator

Inherits:
Object
  • Object
show all
Defined in:
lib/smarter_json/generator.rb

Constant Summary collapse

ESCAPE =
{
  '"' => '\\"', "\\" => "\\\\", "\b" => "\\b", "\f" => "\\f",
  "\n" => "\\n", "\r" => "\\r", "\t" => "\\t"
}.freeze
ESCAPE_RE =

“, backslash, and control chars 0x00-0x1F must be escaped; everything else (including multi-byte UTF-8) is emitted raw — valid JSON.

/["\\\x00-\x1f]/.freeze
KNOWN_OPTIONS =

Strict configuration: an unknown writer option is a caller bug, so it raises rather than being silently ignored.

%i[format indent ascii_only script_safe sort_keys coerce allow_nan].freeze

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Generator

Returns a new instance of Generator.



41
42
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
# File 'lib/smarter_json/generator.rb', line 41

def initialize(options = {})
  unknown = options.keys - KNOWN_OPTIONS
  unless unknown.empty?
    raise ArgumentError, "SmarterJSON.generate: unknown option#{unknown.size == 1 ? '' : 's'} " \
                         "#{unknown.map(&:inspect).join(', ')} — valid keys: #{KNOWN_OPTIONS.map(&:inspect).join(', ')}"
  end

  @format = options.fetch(:format, :json)
  unless %i[json ndjson].include?(@format)
    raise ArgumentError, "unknown writer format: #{@format.inspect} (expected :json or :ndjson)"
  end

  @indent = options.fetch(:indent, 0) # spaces per nesting level; 0 = compact (default)
  unless @indent.is_a?(Integer) && @indent >= 0
    raise ArgumentError, "indent must be a non-negative Integer, got #{@indent.inspect}"
  end
  if @indent > 0 && @format == :ndjson
    raise ArgumentError, "indent is not compatible with format: :ndjson (each record must be a single line)"
  end

  @pretty = @indent > 0

  @ascii_only  = boolean_option(options, :ascii_only)  # escape non-ASCII as \uXXXX
  @script_safe = boolean_option(options, :script_safe) # escape </ and U+2028 / U+2029
  @sort_keys   = boolean_option(options, :sort_keys)   # emit object keys in sorted order
  @coerce      = boolean_option(options, :coerce)      # convert unknown types via as_json / to_json
  @allow_nan   = boolean_option(options, :allow_nan)   # emit NaN / Infinity / -Infinity (JSON5) instead of raising
  @escape_re   = build_escape_re
end

Instance Method Details

#generate(obj) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/smarter_json/generator.rb', line 71

def generate(obj)
  buf = +""
  if @format == :ndjson
    if obj.is_a?(Array)
      obj.each do |v|
        emit(v, buf)
        buf << "\n"
      end
    else
      emit(obj, buf)
      buf << "\n"
    end
  else
    emit(obj, buf)
  end
  buf
end