lib/json/streamer.rb in json-streamer-0.3.0 vs lib/json/streamer.rb in json-streamer-0.4.0
- old
+ new
@@ -2,94 +2,112 @@
require "json/stream"
module Json
module Streamer
class JsonStreamer
+
+ attr_reader :aggregator
+
def initialize(file_io, chunk_size = 1000)
@parser = JSON::Stream::Parser.new
@file_io = file_io
@chunk_size = chunk_size
- @object_nesting_level = 0
+ @current_nesting_level = -1
@current_key = nil
@aggregator = {}
@temp_aggregator_keys = {}
@parser.start_object {start_object}
@parser.start_array {start_array}
@parser.key {|k| key(k)}
- @parser.value {|v| value(v)}
end
- def get_objects_from_level(yield_nesting_level)
- @yield_nesting_level = yield_nesting_level
+ def get(nesting_level:-1, key:nil)
+ @yield_nesting_level = nesting_level
+ @wanted_key = key
+ @parser.value do |v|
+ if @aggregator[@current_nesting_level].kind_of? Array
+ @aggregator[@current_nesting_level] << v
+ else
+ @aggregator[@current_nesting_level][@current_key] = v
+ if yield_value?
+ yield v
+ end
+ end
+ end
+
# Callback containing yield has be defined in the method called via block
@parser.end_object do
- if @object_nesting_level.eql? @yield_nesting_level
- yield @aggregator[@object_nesting_level].clone
+ if yield_object?
+ yield @aggregator[@current_nesting_level].clone
# TODO probably can be faster than reject!{true}
- @aggregator[@object_nesting_level].reject!{true}
+ @aggregator[@current_nesting_level].reject!{true}
else
merge_up
end
- @object_nesting_level -= 1
+ @current_nesting_level -= 1
end
@parser.end_array do
- if @object_nesting_level.eql? @yield_nesting_level
- yield @aggregator[@object_nesting_level].clone
+ if yield_object?
+ yield @aggregator[@current_nesting_level].clone
# TODO probably can be faster than reject!{true}
- @aggregator[@object_nesting_level].reject!{true}
+ @aggregator[@current_nesting_level].reject!{true}
else
merge_up
end
- @object_nesting_level -= 1
+ @current_nesting_level -= 1
end
@file_io.each(@chunk_size) do |chunk|
@parser << chunk
end
end
+ def yield_object?
+ @current_nesting_level.eql? @yield_nesting_level or (not @wanted_key.nil? and @wanted_key == @temp_aggregator_keys[@current_nesting_level-1])
+ end
+
+ def yield_value?
+ @wanted_key == @current_key
+ end
+
def start_object
- @temp_aggregator_keys[@object_nesting_level] = @current_key
- @object_nesting_level += 1
- @aggregator[@object_nesting_level] = {}
+ @temp_aggregator_keys[@current_nesting_level] = @current_key
+ @current_nesting_level += 1
+ @aggregator[@current_nesting_level] = {}
end
def start_array
- @temp_aggregator_keys[@object_nesting_level] = @current_key
- @object_nesting_level += 1
- @aggregator[@object_nesting_level] = []
+ @temp_aggregator_keys[@current_nesting_level] = @current_key
+ @current_nesting_level += 1
+ @aggregator[@current_nesting_level] = []
end
def key k
@current_key = k
end
def value v
- if @aggregator[@object_nesting_level].kind_of? Array
- @aggregator[@object_nesting_level] << v
- else
- @aggregator[@object_nesting_level][@current_key] = v
- end
+
end
def merge_up
- return if @object_nesting_level == 1
- previous_object_nesting_level = @object_nesting_level - 1
- if @aggregator[previous_object_nesting_level].kind_of? Array
- @aggregator[previous_object_nesting_level] << @aggregator[@object_nesting_level]
+ return if @current_nesting_level == 0
+ previous_nesting_level = @current_nesting_level - 1
+ if @aggregator[previous_nesting_level].kind_of? Array
+ @aggregator[previous_nesting_level] << @aggregator[@current_nesting_level]
else
- @aggregator[previous_object_nesting_level][@temp_aggregator_keys[previous_object_nesting_level]] = @aggregator[@object_nesting_level]
+ @aggregator[previous_nesting_level][@temp_aggregator_keys[previous_nesting_level]] = @aggregator[@current_nesting_level]
end
- @aggregator.delete(@object_nesting_level)
+ @aggregator.delete(@current_nesting_level)
@aggregator
end
end
end
end