Fix issue 183: Number fields failed to parse dumped values for +/- Infinity and NaN
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java b/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
index 1ce65c1..5b51b25 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
@@ -273,7 +273,8 @@
}
}
- public static class ConstructYamlNumber extends AbstractConstruct {
+ public class ConstructYamlNumber extends AbstractConstruct {
+
private final NumberFormat nf = NumberFormat.getInstance();
public Object construct(Node node) {
@@ -281,8 +282,15 @@
try {
return nf.parse(scalar.getValue());
} catch (ParseException e) {
- throw new IllegalArgumentException("Unable to parse as Number: "
- + scalar.getValue());
+ String lowerCaseValue = scalar.getValue().toLowerCase();
+ if (lowerCaseValue.contains("inf") || lowerCaseValue.contains("nan")) {
+ // Non-finites such as (+/-)infinity and NaN are not parseable by NumberFormat when these `Double` values are dumped by snakeyaml.
+ // Delegate to the `Tag.FLOAT` constructor when for this expected failure cause.
+ return (Number) yamlConstructors.get(Tag.FLOAT).construct(node);
+ } else {
+ throw new IllegalArgumentException("Unable to parse as Number: "
+ + scalar.getValue());
+ }
}
}
}
diff --git a/src/test/java/org/yaml/snakeyaml/issues/issue183/NumberBeanTest.java b/src/test/java/org/yaml/snakeyaml/issues/issue183/NumberBeanTest.java
index 8842a3c..af63b3c 100644
--- a/src/test/java/org/yaml/snakeyaml/issues/issue183/NumberBeanTest.java
+++ b/src/test/java/org/yaml/snakeyaml/issues/issue183/NumberBeanTest.java
@@ -21,7 +21,7 @@
public class NumberBeanTest extends TestCase {
- public void testInfinityFloatBean() throws Exception {
+ public void testNumberBean() throws Exception {
NumberBean number = new NumberBean();
number.number = 1;
@@ -31,4 +31,66 @@
NumberBean loaded = yaml.loadAs(dump, NumberBean.class);
assertEquals(new Long(1), loaded.number);
}
+
+ public void testNumberAsFloatInfinity() throws Exception {
+ NumberBean number = new NumberBean();
+ number.number = Float.POSITIVE_INFINITY;
+
+ Yaml yaml = new Yaml();
+ String dump = yaml.dump(number);
+ NumberBean loaded = yaml.loadAs(dump, NumberBean.class);
+ assertEquals(Float.POSITIVE_INFINITY, loaded.number.floatValue());
+ }
+
+ public void testNumberAsDoubleInfinity() throws Exception {
+ NumberBean number = new NumberBean();
+ number.number = Double.POSITIVE_INFINITY;
+
+ Yaml yaml = new Yaml();
+ String dump = yaml.dump(number);
+ NumberBean loaded = yaml.loadAs(dump, NumberBean.class);
+ assertEquals(Double.POSITIVE_INFINITY, loaded.number.doubleValue());
+ }
+
+ public void testNumberAsNegativeFloatInfinity() throws Exception {
+ NumberBean number = new NumberBean();
+ number.number = Float.NEGATIVE_INFINITY;
+
+ Yaml yaml = new Yaml();
+ String dump = yaml.dump(number);
+ NumberBean loaded = yaml.loadAs(dump, NumberBean.class);
+ assertEquals(Float.NEGATIVE_INFINITY, loaded.number.floatValue());
+ }
+
+ public void testNumberAsNegativeDoubleInfinity() throws Exception {
+ NumberBean number = new NumberBean();
+ number.number = Double.NEGATIVE_INFINITY;
+
+ Yaml yaml = new Yaml();
+ String dump = yaml.dump(number);
+ NumberBean loaded = yaml.loadAs(dump, NumberBean.class);
+ assertEquals(Double.NEGATIVE_INFINITY, loaded.number.doubleValue());
+ }
+
+
+ public void testNumberAsFloatNaN() throws Exception {
+ NumberBean number = new NumberBean();
+ number.number = Float.NaN;
+
+ Yaml yaml = new Yaml();
+ String dump = yaml.dump(number);
+ NumberBean loaded = yaml.loadAs(dump, NumberBean.class);
+ assertEquals(Float.NaN, loaded.number.floatValue());
+ }
+
+ public void testNumberAsDoubleNaN() throws Exception {
+ NumberBean number = new NumberBean();
+ number.number = Double.NaN;
+
+ Yaml yaml = new Yaml();
+ String dump = yaml.dump(number);
+ NumberBean loaded = yaml.loadAs(dump, NumberBean.class);
+ assertEquals(Double.NaN, loaded.number.doubleValue());
+ }
+
}