diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x
index 72c7244ae..b3614acee 100644
--- a/release-notes/CREDITS-2.x
+++ b/release-notes/CREDITS-2.x
@@ -258,3 +258,8 @@ Mathieu Lavigne (@mathieu-lavigne)
* Proposed #45 (and suggested implementation): (csv) Allow skipping ending line break
(`CsvGenerator.Feature.WRITE_LINEFEED_AFTER_LAST_ROW`)
(2.17.0)
+
+Michael Edgar (@MikeEdgar)
+
+* Contributed #465: (yaml) YAML: consider starting `#` and ending `:` as quotable characters
+ (2.17.0)
diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x
index 0f409cdd9..abaebaccb 100644
--- a/release-notes/VERSION-2.x
+++ b/release-notes/VERSION-2.x
@@ -14,6 +14,9 @@ Active Maintainers:
=== Releases ===
------------------------------------------------------------------------
+#465: (yaml) YAML: consider starting `#` and ending `:` as quotable characters
+ (contributed by Michael E)
+
2.17.0-rc1 (26-Feb-2024)
#45: (csv) Allow skipping ending line break
diff --git a/yaml/src/main/java/tools/jackson/dataformat/yaml/util/StringQuotingChecker.java b/yaml/src/main/java/tools/jackson/dataformat/yaml/util/StringQuotingChecker.java
index d7a7afff5..dde840ab2 100644
--- a/yaml/src/main/java/tools/jackson/dataformat/yaml/util/StringQuotingChecker.java
+++ b/yaml/src/main/java/tools/jackson/dataformat/yaml/util/StringQuotingChecker.java
@@ -8,7 +8,7 @@
* Helper class that defines API used by
* {@link tools.jackson.dataformat.yaml.YAMLGenerator}
* to check whether property names and String values need to be quoted or not.
- * Also contains default logic implementation; may be sub-classes to provide
+ * Also contains default logic implementation; may be sub-classed to provide
* alternate implementation.
*
* @since 2.12
@@ -58,10 +58,10 @@ public abstract class StringQuotingChecker
* Helper method that sub-classes may use to see if given String value is
* one of:
*
- * - YAML 1.1 keyword representing
+ *
- YAML 1.1 keyword representing
* boolean
*
- * - YAML 1.1 keyword representing
+ *
- YAML 1.1 keyword representing
* null value
*
* - empty String (length 0)
@@ -142,20 +142,16 @@ protected boolean valueHasQuotableChar(String inputStr)
return true;
case '#':
// [dataformats-text#201]: limit quoting with MINIMIZE_QUOTES
- if (i > 0) {
- char d = inputStr.charAt(i-1);
- if (' ' == d || '\t' == d) {
- return true;
- }
+ // (but not recognized as comment unless starts line or preceded by whitespace)
+ if (precededOnlyByBlank(inputStr, i)) {
+ return true;
}
break;
case ':':
// [dataformats-text#201]: limit quoting with MINIMIZE_QUOTES
- if (i < (end-1)) {
- char d = inputStr.charAt(i + 1);
- if (' ' == d || '\t' == d) {
- return true;
- }
+ // (but recognized as separator only if end-of-line or followed by whitespace)
+ if (followedOnlyByBlank(inputStr, i)) {
+ return true;
}
break;
default:
@@ -164,6 +160,27 @@ protected boolean valueHasQuotableChar(String inputStr)
return false;
}
+ // @since 2.17
+ protected boolean precededOnlyByBlank(String inputStr, int offset) {
+ if (offset == 0) {
+ return true;
+ }
+ return isBlank(inputStr.charAt(offset - 1));
+ }
+
+ // @since 2.17
+ protected boolean followedOnlyByBlank(String inputStr, int offset) {
+ if (offset == inputStr.length() - 1) {
+ return true;
+ }
+ return isBlank(inputStr.charAt(offset + 1));
+ }
+
+ // @since 2.17
+ protected boolean isBlank(char value) {
+ return (' ' == value || '\t' == value);
+ }
+
/**
* Looks like we may get names with "funny characters" so.
*
@@ -199,7 +216,7 @@ public static class Default
public Default() { }
public static Default instance() { return INSTANCE; }
-
+
/**
* Default implementation will call
* {@link #isReservedKeyword(String)} and
diff --git a/yaml/src/test/java/tools/jackson/dataformat/yaml/ser/GeneratorWithMinimizeTest.java b/yaml/src/test/java/tools/jackson/dataformat/yaml/ser/GeneratorWithMinimizeTest.java
index 1162bf6ce..e369ceeb2 100644
--- a/yaml/src/test/java/tools/jackson/dataformat/yaml/ser/GeneratorWithMinimizeTest.java
+++ b/yaml/src/test/java/tools/jackson/dataformat/yaml/ser/GeneratorWithMinimizeTest.java
@@ -128,25 +128,22 @@ public void testMinimizeQuotesWithStringsContainingSpecialChars() throws Excepti
"key: f:off", yaml);
- /* scenarios with single quoted scalars */
+ /* scenarios with double quoted scalars */
content = Collections.singletonMap("key", "::");
yaml = MINIM_MAPPER.writeValueAsString(content).trim();
assertEquals("---\n" +
- "key: '::'", yaml);
+ "key: \"::\"", yaml);
content = Collections.singletonMap("key", "#");
yaml = MINIM_MAPPER.writeValueAsString(content).trim();
assertEquals("---\n" +
- "key: '#'", yaml);
+ "key: \"#\"", yaml);
content = Collections.singletonMap("key", "#a");
yaml = MINIM_MAPPER.writeValueAsString(content).trim();
assertEquals("---\n" +
- "key: '#a'", yaml);
-
-
- /* scenarios with double quoted scalars */
+ "key: \"#a\"", yaml);
content = Collections.singletonMap("key", "a[b");
yaml = MINIM_MAPPER.writeValueAsString(content).trim();