diff --git a/spec/std/yaml/serialization_spec.cr b/spec/std/yaml/serialization_spec.cr index 414d44541fab..de0a111b7a86 100644 --- a/spec/std/yaml/serialization_spec.cr +++ b/spec/std/yaml/serialization_spec.cr @@ -390,6 +390,18 @@ describe "YAML serialization" do Bytes.from_yaml("!!binary aGVsbG8=").should eq("hello".to_slice) end + describe "Union.from_yaml" do + it "String priorization" do + (Int32 | String).from_yaml(%(42)).should eq 42 + (Int32 | String).from_yaml(%("42")).should eq "42" + + (String | UInt32).from_yaml(%(42)).should eq 42 + (String | UInt32).from_yaml(%("42")).should eq "42" + + (Int32 | UInt32).from_yaml(%("42")).should eq 42 + end + end + describe "parse exceptions" do it "has correct location when raises in Nil#from_yaml" do ex = expect_raises(YAML::ParseException) do diff --git a/src/yaml/enums.cr b/src/yaml/enums.cr index 2ab6789e0a4c..bf1d44fa2043 100644 --- a/src/yaml/enums.cr +++ b/src/yaml/enums.cr @@ -20,6 +20,10 @@ module YAML DOUBLE_QUOTED LITERAL FOLDED + + def quoted? + single_quoted? || double_quoted? + end end enum SequenceStyle diff --git a/src/yaml/from_yaml.cr b/src/yaml/from_yaml.cr index b9b6e7fae45c..227adb64c3c0 100644 --- a/src/yaml/from_yaml.cr +++ b/src/yaml/from_yaml.cr @@ -298,6 +298,13 @@ def Union.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node) # So, we give a chance first to types in the union to be parsed. {% string_type = T.find { |type| type == ::String } %} + {% if string_type %} + if node.as?(YAML::Nodes::Scalar).try(&.style.quoted?) + # do prefer String if it's a quoted scalar though + return String.new(ctx, node) + end + {% end %} + {% for type in T %} {% unless type == string_type %} begin