diff --git a/yaml/src/main/java/com/fasterxml/jackson/dataformat/yaml/YAMLGenerator.java b/yaml/src/main/java/com/fasterxml/jackson/dataformat/yaml/YAMLGenerator.java
index 120b2aaf9..3bba7f344 100644
--- a/yaml/src/main/java/com/fasterxml/jackson/dataformat/yaml/YAMLGenerator.java
+++ b/yaml/src/main/java/com/fasterxml/jackson/dataformat/yaml/YAMLGenerator.java
@@ -184,6 +184,19 @@ private Feature(boolean defaultState) {
"on", "On", "ON", "off", "Off", "OFF"
));
+ /**
+ * As per YAML null
+ * and boolean type specs,
+ * better retain quoting for some values
+ */
+ private final static Set RESERVED_VALUES = new HashSet<>(Arrays.asList(
+ "y", "Y", "n", "N",
+ "yes", "Yes", "YES", "no", "No", "NO",
+ "true", "True", "TRUE", "false", "False", "FALSE",
+ "on", "On", "ON", "off", "Off", "OFF",
+ "null", "Null", "NULL"
+));
+
/*
/**********************************************************
/* Configuration
@@ -571,10 +584,12 @@ public void writeString(String text) throws IOException,JsonGenerationException
}
_verifyValueWrite("write String value");
Character style = STYLE_QUOTED;
- if (Feature.MINIMIZE_QUOTES.enabledIn(_formatFeatures) && !isBooleanContent(text)) {
+ if (Feature.MINIMIZE_QUOTES.enabledIn(_formatFeatures)) {
// If this string could be interpreted as a number, it must be quoted.
- if (Feature.ALWAYS_QUOTE_NUMBERS_AS_STRINGS.enabledIn(_formatFeatures)
- && PLAIN_NUMBER_P.matcher(text).matches()) {
+ if (_valueNeedsQuoting(text)
+ || (Feature.ALWAYS_QUOTE_NUMBERS_AS_STRINGS.enabledIn(_formatFeatures)
+ && PLAIN_NUMBER_P.matcher(text).matches())
+ ) {
style = STYLE_QUOTED;
} else if (text.indexOf('\n') >= 0) {
style = STYLE_LITERAL;
@@ -587,8 +602,22 @@ public void writeString(String text) throws IOException,JsonGenerationException
_writeScalar(text, "string", style);
}
- private boolean isBooleanContent(String text) {
- return text.equals("true") || text.equals("false");
+ private boolean _valueNeedsQuoting(String name) {
+ switch (name.charAt(0)) { // caller ensures no empty String
+ // First, reserved name starting chars:
+ case 'f': // false
+ case 'o': // on/off
+ case 'n': // null/n/no
+ case 't': // true
+ case 'y': // y/yes
+ case 'F': // False/FALSE
+ case 'O': // On/Off/ON/OFF
+ case 'N': // Null/NULL/N/No/NO
+ case 'T': // True/TRUE
+ case 'Y': // Y/Yes/YES
+ return RESERVED_VALUES.contains(name);
+ }
+ return false;
}
@Override
diff --git a/yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/misc/ReservedValuesTest.java b/yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/misc/ReservedValuesTest.java
new file mode 100644
index 000000000..7edd71064
--- /dev/null
+++ b/yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/misc/ReservedValuesTest.java
@@ -0,0 +1,35 @@
+package com.fasterxml.jackson.dataformat.yaml.misc;
+
+import java.util.*;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.ModuleTestBase;
+
+public class ReservedValuesTest extends ModuleTestBase
+{
+ private final ObjectMapper MAPPER = newObjectMapper();
+
+ public void testQuotingOfBooleanValues() throws Exception
+ {
+ for (String value : new String[] {
+ "null", "Null", "NULL",
+ "true", "True", "TRUE",
+ "false", "False", "FALSE",
+ "yes", "Yes", "YES",
+ "no" "No", "NO",
+ "y", "Y", "n", "N",
+ "on", "On", "ON",
+ "off" "Off", "OFF"
+ }) {
+ _testQuotingOfBooleanValues(value);
+ }
+ }
+
+ private void _testQuotingOfBooleanValues(String value) throws Exception
+ {
+ final Map input = Collections.singletonMap("key", value);
+ final String doc = trimDocMarker(MAPPER.writeValueAsString(input).trim());
+
+ assertEquals("key: \""+value+"\"", doc);
+ }
+}