Skip to content

Instantly share code, notes, and snippets.

@akm
Last active December 7, 2018 08:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akm/b9c627bd5974a6dc93df2991138956d3 to your computer and use it in GitHub Desktop.
Save akm/b9c627bd5974a6dc93df2991138956d3 to your computer and use it in GitHub Desktop.
# Summarize JSON structure
# cat source.json | ruby sum_json.rb --key-pattern '\A\-|\-test\z' --format json
require 'json'
require 'yaml'
require 'getoptlong.rb'
parser = GetoptLong.new
parser.set_options(
['--key-pattern', '-k', GetoptLong::OPTIONAL_ARGUMENT],
['--format', '-f', GetoptLong::OPTIONAL_ARGUMENT],
)
@key_regexp = nil
@format = 'yaml'
begin
parser.each_option do |name, arg|
case name
when '--key-pattern', '-k'
@key_regexp = Regexp.new(arg)
when '--format', '-f'
@format = arg
end
end
rescue
exit(1)
end
root = JSON.parse($stdin.read)
def assign(d, k, child)
if d[k] && child
if d[k].is_a?(Hash) && child.is_a?(Hash)
d[k].update(child)
else
if d[k] != child
if [ d[k], child ].sort != ['float64', 'int64']
$stderr.puts("Mismatch! \n#{d[k].inspect}\n#{child.inspect}")
end
end
end
else
d[k] ||= child
end
end
def walk(node)
case node
when Hash
node.each_with_object({}) do |(key, child), d|
k = (@key_regexp && @key_regexp =~ key) ? '(key)' : key
assign(d, k, walk(child))
end
when Array
node.each_with_object({}) do |child, d|
assign(d, '(index)', walk(child))
end
when String then 'string'
when Integer then 'int64'
when Float then 'float64'
when TrueClass then 'bool'
when FalseClass then 'bool'
when NilClass then 'null'
else
$stderr.puts("unknown value: #{node.inspect}")
end
end
r = walk(root)
output =
case @format
when 'yaml' then YAML.dump(r)
when 'json' then JSON.pretty_generate(r)
else raise "Unsupported format: #{@format.inspect}"
end
$stdout.puts(output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment