Skip to content

Instantly share code, notes, and snippets.

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 asterite/178ec225dde3063c6a3d545c1cfea25f to your computer and use it in GitHub Desktop.
Save asterite/178ec225dde3063c6a3d545c1cfea25f to your computer and use it in GitHub Desktop.
require "spec"
require "json"
require "yaml"
class JSON::Builder
def next_is_object_key?
state = @state.last
state.is_a?(ObjectState) && state.name
end
end
module OQ
module Stream
def self.yaml_to_json(input : IO, output : IO)
yaml = YAML::PullParser.new(input)
json = JSON::Builder.new(output)
yaml.read_stream do
while true
case yaml.kind
when .document_start?
json.start_document
when .document_end?
json.end_document
yaml.read_next
break
when .scalar?
string = yaml.value
if json.next_is_object_key?
json.scalar(string)
else
scalar = YAML::Schema::Core.parse_scalar(string)
case scalar
when Nil
json.scalar(scalar)
when Bool
json.scalar(scalar)
when Int64
json.scalar(scalar)
when Float64
json.scalar(scalar)
else
json.scalar(string)
end
end
when .sequence_start?
json.start_array
when .sequence_end?
json.end_array
when .mapping_start?
json.start_object
when .mapping_end?
json.end_object
end
yaml.read_next
end
end
end
def self.json_to_yaml(input : IO, output : IO)
json = JSON::PullParser.new(input)
yaml = YAML::Builder.new(output)
yaml.stream do
yaml.document do
while true
case json.kind
when :null
yaml.scalar(nil)
when :bool
yaml.scalar(json.bool_value)
when :int
yaml.scalar(json.int_value)
when :float
yaml.scalar(json.float_value)
when :string
if YAML::Schema::Core.reserved_string?(json.string_value)
yaml.scalar(json.string_value, style: :double_quoted)
else
yaml.scalar(json.string_value)
end
when :begin_array
yaml.start_sequence
when :end_array
yaml.end_sequence
when :begin_object
yaml.start_mapping
when :end_object
yaml.end_mapping
when :EOF
break
end
json.read_next
end
end
end
end
end
end
private def assert_stream_yaml_to_json(input, file = __FILE__, line = __LINE__)
it "stream #{input.inspect} YAML to JSON", file, line do
io = IO::Memory.new(input.to_yaml)
output = IO::Memory.new
OQ::Stream.yaml_to_json(io, output)
string = output.to_s
input.to_json.should eq(string)
end
end
private def assert_stream_json_to_yaml(input, file = __FILE__, line = __LINE__)
it "stream #{input.inspect} JSON to YAML", file, line do
io = IO::Memory.new(input.to_json)
output = IO::Memory.new
OQ::Stream.json_to_yaml(io, output)
string = output.to_s
input.to_yaml.should eq(string)
end
end
describe "OQ::Stream.yaml_to_json" do
assert_stream_yaml_to_json(nil)
assert_stream_yaml_to_json(true)
assert_stream_yaml_to_json(false)
assert_stream_yaml_to_json("hello")
assert_stream_yaml_to_json(123)
assert_stream_yaml_to_json(123.45)
assert_stream_yaml_to_json([] of Nil)
assert_stream_yaml_to_json([1, 2, 3])
assert_stream_yaml_to_json({} of Nil => Nil)
assert_stream_yaml_to_json({1 => 2, 3 => 4})
assert_stream_yaml_to_json({"1" => 2, "3" => 4})
assert_stream_yaml_to_json({"1" => [2, {"3" => 4}, 5], "6" => {"7" => 8}, "9" => {10 => true}})
end
describe "OQ::Stream.json_to_yaml" do
assert_stream_json_to_yaml(nil)
assert_stream_json_to_yaml(true)
assert_stream_json_to_yaml(false)
assert_stream_json_to_yaml("hello")
assert_stream_json_to_yaml(123)
assert_stream_json_to_yaml(123.45)
assert_stream_json_to_yaml([] of Nil)
assert_stream_json_to_yaml([1, 2, 3])
assert_stream_json_to_yaml({} of Nil => Nil)
assert_stream_json_to_yaml({"1" => 2, "3" => 4})
assert_stream_json_to_yaml({"1" => [2, {"3" => 4}, 5], "6" => {"7" => 8}, "9" => {"10" => true}})
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment