lib/json-write-stream/stateful.rb in json-write-stream-1.2.0 vs lib/json-write-stream/stateful.rb in json-write-stream-2.0.0
- old
+ new
@@ -1,37 +1,49 @@
# encoding: UTF-8
+require 'json'
+
class JsonWriteStream
class NotInObjectError < StandardError; end
class NotInArrayError < StandardError; end
class EndOfStreamError < StandardError; end
class StatefulWriter
- attr_reader :stream, :index, :stack, :closed
- alias :closed? :closed
+ attr_reader :stream, :stack, :index, :closed, :options
+ alias_method :closed?, :closed
- def initialize(stream)
+ def initialize(stream, options = {})
@stream = stream
- @index = 0
@stack = []
@closed = false
- after_initialize
+ @options = options
+ @index = 0
end
- def after_initialize
- end
-
def write_object(*args)
check_eos
- current.write_object(*args) if current
- stack.push(StatefulObjectWriter.new(stream))
+ new_indent_level = 1
+
+ if current
+ current.write_object(*args)
+ new_indent_level = current.indent_level + 1
+ end
+
+ stack.push(StatefulObjectWriter.new(self, new_indent_level))
end
def write_array(*args)
check_eos
- current.write_array(*args) if current
- stack.push(StatefulArrayWriter.new(stream))
+
+ new_indent_level = 1
+
+ if current
+ current.write_array(*args)
+ new_indent_level = current.indent_level + 1
+ end
+
+ stack.push(StatefulArrayWriter.new(self, new_indent_level))
end
def write_key_value(*args)
check_eos
current.write_key_value(*args)
@@ -91,68 +103,126 @@
def eos?
(stack.size == 0 && index > 0) || closed?
end
+ def pretty?
+ options.fetch(:pretty, false)
+ end
+
+ def indent_size
+ options.fetch(:indent_size, 2)
+ end
+
protected
+ def increment
+ @index += 1
+ end
+
def check_eos
if eos?
raise EndOfStreamError, 'end of stream.'
end
end
def current
stack.last
end
+ end
+ class BaseWriter
+ attr_reader :writer, :indent_level, :index
+
+ def initialize(writer, indent_level)
+ @writer = writer
+ @indent_level = indent_level
+ @index = 0
+ after_initialize
+ end
+
+ def after_initialize
+ end
+
+ def stream
+ writer.stream
+ end
+
+ def increment
+ @index += 1
+ end
+
+ def indent(level = indent_level)
+ stream.write(' ' * indent_size * level) if pretty?
+ end
+
+ def indent_size
+ writer.indent_size
+ end
+
def escape(str)
JSON.generate([str])[1..-2]
end
def write_comma
- stream.write(',') if index > 0
+ if index > 0
+ stream.write(",")
+ write_newline
+ end
end
- def increment
- @index += 1
+ def write_colon
+ stream.write(':')
+ stream.write(' ') if pretty?
end
+
+ def write_newline
+ stream.write("\n") if pretty?
+ end
+
+ def pretty?
+ writer.pretty?
+ end
end
- class StatefulObjectWriter < StatefulWriter
+ class StatefulObjectWriter < BaseWriter
def after_initialize
- stream.write('{')
+ stream.write("{")
+ write_newline
end
# prep work (array is written afterwards)
def write_array(key)
write_comma
increment
+ indent
write_key(key)
- stream.write(':')
+ write_colon
end
# prep work (object is written afterwards)
def write_object(key)
write_comma
increment
+ indent
write_key(key)
- stream.write(':')
+ write_colon
end
- def write_key_value(key, value, options = DEFAULT_OPTIONS)
+ def write_key_value(key, value)
write_comma
- stream.write(options.fetch(:before, DEFAULT_OPTIONS[:before]))
increment
+ indent
write_key(key)
- stream.write(':')
- stream.write(options.fetch(:between, DEFAULT_OPTIONS[:between]))
+ write_colon
stream.write(escape(value))
end
def close
- stream.write('}')
+ write_newline
+ indent(indent_level - 1)
+ stream.write("}")
end
def is_object?
true
end
@@ -171,35 +241,40 @@
raise ArgumentError, "'#{key}' must be a string"
end
end
end
- class StatefulArrayWriter < StatefulWriter
+ class StatefulArrayWriter < BaseWriter
def after_initialize
- stream.write('[')
+ stream.write("[")
+ write_newline
end
- def write_element(element, options = DEFAULT_OPTIONS)
+ def write_element(element)
write_comma
- stream.write(options.fetch(:before, DEFAULT_OPTIONS[:before]))
increment
+ indent
stream.write(escape(element))
end
# prep work
def write_array
write_comma
increment
+ indent
end
# prep work
def write_object
write_comma
increment
+ indent
end
def close
- stream.write(']')
+ write_newline
+ indent(indent_level - 1)
+ stream.write("]")
end
def is_object?
false
end