Created
July 14, 2019 21:48
-
-
Save asterite/178ec225dde3063c6a3d545c1cfea25f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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