@@ -18,33 +18,24 @@ public abstract class StringQuotingChecker
18
18
{
19
19
private static final long serialVersionUID = 1L ;
20
20
21
- /* As per <a href="https://yaml.org/type/bool.html">YAML Spec</a> there are a few
22
- * aliases for booleans, and we better quote such values as keys; although Jackson
23
- * itself has no problems dealing with them, some other tools do have.
24
- */
25
- // 02-Apr-2019, tatu: Some names will look funny if escaped: let's leave out
26
- // single letter case (esp so 'y' won't get escaped)
27
- // 17-Sep-2020, tatu: [dataformats-text#226] No, let's be consistent w/ values
28
- private final static Set <String > DEFAULT_QUOTABLE_NAMES = new HashSet <>(Arrays .asList (
29
- "y" , "Y" , "n" , "N" ,
30
- "yes" , "Yes" , "YES" , "no" , "No" , "NO" ,
31
- "true" , "True" , "TRUE" , "false" , "False" , "FALSE" ,
32
- "on" , "On" , "ON" , "off" , "Off" , "OFF" ,
33
- "null" , "Null" , "NULL"
34
- ));
35
-
36
21
/**
37
22
* As per YAML <a href="https://yaml.org/type/null.html">null</a>
38
23
* and <a href="https://yaml.org/type/bool.html">boolean</a> type specs,
39
- * better retain quoting for some values
24
+ * better retain quoting for some keys (property names) and values.
40
25
*/
41
- private final static Set <String > DEFAULT_QUOTABLE_VALUES = new HashSet <>(Arrays .asList (
26
+ private final static Set <String > RESERVED_KEYWORDS = new HashSet <>(Arrays .asList (
27
+ // 02-Apr-2019, tatu: Some names will look funny if escaped: let's leave out
28
+ // single letter case (esp so 'y' won't get escaped)
29
+ // 17-Sep-2020, tatu: [dataformats-text#226] No, let's be consistent w/ values
42
30
"false" , "False" , "FALSE" ,
31
+ "n" , "N" ,
32
+ "no" , "No" , "NO" ,
43
33
"null" , "Null" , "NULL" ,
44
- "on" , "On" , "ON" , "off" , "Off" , "OFF" ,
34
+ "on" , "On" , "ON" ,
35
+ "off" , "Off" , "OFF" ,
45
36
"true" , "True" , "TRUE" ,
46
- "y" , "Y" , "n" , "N" ,
47
- "yes" , "Yes" , "YES" , "no" , "No" , "NO"
37
+ "y" , "Y" ,
38
+ "yes" , "Yes" , "YES"
48
39
));
49
40
50
41
/**
@@ -53,48 +44,45 @@ public abstract class StringQuotingChecker
53
44
* to check whether given property name should be quoted: usually
54
45
* to prevent it from being read as non-String key (boolean or number)
55
46
*/
56
- public boolean needToQuoteName (String name )
57
- {
58
- // empty String does indeed require quoting
59
- if (name .length () == 0 ) {
60
- return true ;
61
- }
62
- switch (name .charAt (0 )) {
63
- // First, reserved name starting chars:
64
- case 'f' : // false
65
- case 'n' : // no/n/null
66
- case 'o' : // on/off
67
- case 't' : // true
68
- case 'y' : // yes/y
69
- case 'F' : // False
70
- case 'N' : // No/N/Null
71
- case 'O' : // On/Off
72
- case 'T' : // True
73
- case 'Y' : // Yes/Y
74
- return isDefaultQuotableName (name );
75
-
76
- // And then numbers
77
- case '0' : case '1' : case '2' : case '3' : case '4' :
78
- case '5' : case '6' : case '7' : case '8' : case '9' :
79
- case '-' : case '+' : case '.' :
80
- return true ;
81
- }
82
- return false ;
83
- }
47
+ public abstract boolean needToQuoteName (String name );
84
48
85
49
/**
86
50
* Method called by
87
51
* {@link com.fasterxml.jackson.dataformat.yaml.YAMLGenerator}
88
52
* to check whether given String value should be quoted: usually
89
- * to prevent it from being value of different type (boolean or number)
53
+ * to prevent it from being value of different type (boolean or number).
90
54
*/
91
- public boolean needToQuoteValue (String value )
92
- {
93
- // empty String does indeed require quoting
55
+ public abstract boolean needToQuoteValue (String value );
56
+
57
+ /**
58
+ * Helper method that sub-classes may use to see if given String value is
59
+ * one of:
60
+ *<ul>
61
+ * <li>YAML 1.1 keyword representing
62
+ * <a href="https://yaml.org/type/bool.html">boolean</a>
63
+ * </li>
64
+ * <li>YAML 1.1 keyword representing
65
+ * <a href="https://yaml.org/type/null.html">null</a> value
66
+ * </li>
67
+ * <li>empty String (length 0)
68
+ * </li>
69
+ *</li>
70
+ * and returns {@code true} if so.
71
+ *
72
+ * @param value String to check
73
+ *
74
+ * @return {@code true} if given value is a Boolean or Null representation
75
+ * (as per YAML 1.1 specification) or empty String
76
+ */
77
+ protected boolean isReservedKeyword (String value ) {
94
78
if (value .length () == 0 ) {
95
79
return true ;
96
80
}
97
- switch (value .charAt (0 )) {
81
+ return _isReservedKeyword (value .charAt (0 ), value );
82
+ }
83
+
84
+ protected boolean _isReservedKeyword (int firstChar , String name ) {
85
+ switch (firstChar ) {
98
86
// First, reserved name starting chars:
99
87
case 'f' : // false
100
88
case 'n' : // no/n/null
@@ -106,20 +94,32 @@ public boolean needToQuoteValue(String value)
106
94
case 'O' : // On/Off
107
95
case 'T' : // True
108
96
case 'Y' : // Yes/Y
109
- if (isDefaultQuotableValue (value )) {
110
- return true ;
111
- }
112
- break ;
97
+ return RESERVED_KEYWORDS .contains (name );
113
98
}
114
- return valueHasQuotableChar ( value ) ;
99
+ return false ;
115
100
}
116
101
117
- protected boolean isDefaultQuotableName (String name ) {
118
- return DEFAULT_QUOTABLE_NAMES .contains (name );
102
+ /**
103
+ * Helper method that sub-classes may use to see if given String value
104
+ * looks like a YAML 1.1 numeric value and would likely be considered
105
+ * a number when parsing unless quoting is used.
106
+ */
107
+ protected boolean looksLikeYAMLNumber (String name ) {
108
+ if (name .length () > 0 ) {
109
+ return _looksLikeYAMLNumber (name .charAt (0 ), name );
110
+ }
111
+ return false ;
119
112
}
120
113
121
- protected boolean isDefaultQuotableValue (String name ) {
122
- return DEFAULT_QUOTABLE_VALUES .contains (name );
114
+ protected boolean _looksLikeYAMLNumber (int firstChar , String name ) {
115
+ switch (firstChar ) {
116
+ // And then numbers
117
+ case '0' : case '1' : case '2' : case '3' : case '4' :
118
+ case '5' : case '6' : case '7' : case '8' : case '9' :
119
+ case '-' : case '+' : case '.' :
120
+ return true ;
121
+ }
122
+ return false ;
123
123
}
124
124
125
125
/**
@@ -166,7 +166,7 @@ protected boolean valueHasQuotableChar(String inputStr)
166
166
* Default {@link StringQuotingChecker} implementation used unless
167
167
* custom implementation registered.
168
168
*/
169
- public final static class Default
169
+ public static class Default
170
170
extends StringQuotingChecker
171
171
implements java .io .Serializable
172
172
{
@@ -177,5 +177,30 @@ public final static class Default
177
177
public Default () { }
178
178
179
179
public static Default instance () { return INSTANCE ; }
180
+
181
+ /**
182
+ * Default implementation will call
183
+ * {@link #isReservedKeyword(String)} and
184
+ * {@link #looksLikeYAMLNumber(String)} to determine
185
+ * if quoting should be applied.
186
+ */
187
+ @ Override
188
+ public boolean needToQuoteName (String name )
189
+ {
190
+ return isReservedKeyword (name ) || looksLikeYAMLNumber (name );
191
+ }
192
+
193
+ /**
194
+ * Default implementation will call
195
+ * {@link #isReservedKeyword(String)}
196
+ * and {@link #valueHasQuotableChar(String)} to determine
197
+ * if quoting should be applied.
198
+ */
199
+ @ Override
200
+ public boolean needToQuoteValue (String value )
201
+ {
202
+ // Only consider reserved keywords but not numbers?
203
+ return isReservedKeyword (value ) || valueHasQuotableChar (value );
204
+ }
180
205
}
181
206
}
0 commit comments