package com.fasterxml.jackson.dataformat.yaml.util;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

Helper class that defines API used by 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 alternate implementation.
Since:2.12
/** * Helper class that defines API used by * {@link com.fasterxml.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 * alternate implementation. * * @since 2.12 */
public abstract class StringQuotingChecker implements java.io.Serializable { private static final long serialVersionUID = 1L;
As per YAML null and boolean type specs, better retain quoting for some keys (property names) and values.
/** * As per YAML <a href="https://yaml.org/type/null.html">null</a> * and <a href="https://yaml.org/type/bool.html">boolean</a> type specs, * better retain quoting for some keys (property names) and values. */
private final static Set<String> RESERVED_KEYWORDS = new HashSet<>(Arrays.asList( // 02-Apr-2019, tatu: Some names will look funny if escaped: let's leave out // single letter case (esp so 'y' won't get escaped) // 17-Sep-2020, tatu: [dataformats-text#226] No, let's be consistent w/ values "false", "False", "FALSE", "n", "N", "no", "No", "NO", "null", "Null", "NULL", "on", "On", "ON", "off", "Off", "OFF", "true", "True", "TRUE", "y", "Y", "yes", "Yes", "YES" ));
Method called by YAMLGenerator to check whether given property name should be quoted: usually to prevent it from being read as non-String key (boolean or number)
/** * Method called by * {@link com.fasterxml.jackson.dataformat.yaml.YAMLGenerator} * to check whether given property name should be quoted: usually * to prevent it from being read as non-String key (boolean or number) */
public abstract boolean needToQuoteName(String name);
Method called by YAMLGenerator to check whether given String value should be quoted: usually to prevent it from being value of different type (boolean or number).
/** * Method called by * {@link com.fasterxml.jackson.dataformat.yaml.YAMLGenerator} * to check whether given String value should be quoted: usually * to prevent it from being value of different type (boolean or number). */
public abstract boolean needToQuoteValue(String value);
Helper method that sub-classes may use to see if given String value is one of:
  • YAML 1.1 keyword representing boolean
  • YAML 1.1 keyword representing null value
  • empty String (length 0)
  • and returns true if so.
Params:
  • value – String to check
Returns:true if given value is a Boolean or Null representation (as per YAML 1.1 specification) or empty String
/** * Helper method that sub-classes may use to see if given String value is * one of: *<ul> * <li>YAML 1.1 keyword representing * <a href="https://yaml.org/type/bool.html">boolean</a> * </li> * <li>YAML 1.1 keyword representing * <a href="https://yaml.org/type/null.html">null</a> value * </li> * <li>empty String (length 0) * </li> *</li> * and returns {@code true} if so. * * @param value String to check * * @return {@code true} if given value is a Boolean or Null representation * (as per YAML 1.1 specification) or empty String */
protected boolean isReservedKeyword(String value) { if (value.length() == 0) { return true; } return _isReservedKeyword(value.charAt(0), value); } protected boolean _isReservedKeyword(int firstChar, String name) { switch (firstChar) { // First, reserved name starting chars: case 'f': // false case 'n': // no/n/null case 'o': // on/off case 't': // true case 'y': // yes/y case 'F': // False case 'N': // No/N/Null case 'O': // On/Off case 'T': // True case 'Y': // Yes/Y return RESERVED_KEYWORDS.contains(name); case '~': // null alias (see [dataformats-text#274]) return true; } return false; }
Helper method that sub-classes may use to see if given String value looks like a YAML 1.1 numeric value and would likely be considered a number when parsing unless quoting is used.
/** * Helper method that sub-classes may use to see if given String value * looks like a YAML 1.1 numeric value and would likely be considered * a number when parsing unless quoting is used. */
protected boolean looksLikeYAMLNumber(String name) { if (name.length() > 0) { return _looksLikeYAMLNumber(name.charAt(0), name); } return false; } protected boolean _looksLikeYAMLNumber(int firstChar, String name) { switch (firstChar) { // And then numbers case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-' : case '+': case '.': return true; } return false; }
As per YAML Plain Styleunquoted strings are restricted to a reduced charset and must be quoted in case they contain one of the following characters or character combinations.
/** * As per YAML <a href="https://yaml.org/spec/1.2/spec.html#id2788859">Plain Style</a>unquoted * strings are restricted to a reduced charset and must be quoted in case they contain * one of the following characters or character combinations. */
protected boolean valueHasQuotableChar(String inputStr) { final int end = inputStr.length(); for (int i = 0; i < end; ++i) { switch (inputStr.charAt(i)) { case '[': case ']': case '{': case '}': case ',': 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; } } 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; } } break; default: } } return false; }
Default StringQuotingChecker implementation used unless custom implementation registered.
/** * Default {@link StringQuotingChecker} implementation used unless * custom implementation registered. */
public static class Default extends StringQuotingChecker implements java.io.Serializable { private static final long serialVersionUID = 1L; private final static Default INSTANCE = new Default(); public Default() { } public static Default instance() { return INSTANCE; }
Default implementation will call StringQuotingChecker.isReservedKeyword(String) and StringQuotingChecker.looksLikeYAMLNumber(String) to determine if quoting should be applied.
/** * Default implementation will call * {@link #isReservedKeyword(String)} and * {@link #looksLikeYAMLNumber(String)} to determine * if quoting should be applied. */
@Override public boolean needToQuoteName(String name) { return isReservedKeyword(name) || looksLikeYAMLNumber(name); }
Default implementation will call StringQuotingChecker.isReservedKeyword(String) and StringQuotingChecker.valueHasQuotableChar(String) to determine if quoting should be applied.
/** * Default implementation will call * {@link #isReservedKeyword(String)} * and {@link #valueHasQuotableChar(String)} to determine * if quoting should be applied. */
@Override public boolean needToQuoteValue(String value) { // Only consider reserved keywords but not numbers? return isReservedKeyword(value) || valueHasQuotableChar(value); } } }