From 732cc1100ac8f10822c17fdcdc0972fb6ffa43d7 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Tue, 26 Jun 2018 16:31:32 -0700 Subject: [PATCH] Start work on #467 --- .../jackson/core/JsonFactoryBuilder.java | 57 ++++- .../jackson/core/json/JsonReadFeature.java | 221 ++++++++++++++++++ .../core/json/async/AsyncTokenFilterTest.java | 1 + 3 files changed, 277 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/fasterxml/jackson/core/json/JsonReadFeature.java diff --git a/src/main/java/com/fasterxml/jackson/core/JsonFactoryBuilder.java b/src/main/java/com/fasterxml/jackson/core/JsonFactoryBuilder.java index 5063b043f5..6d01399cca 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonFactoryBuilder.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonFactoryBuilder.java @@ -2,13 +2,14 @@ import com.fasterxml.jackson.core.io.CharacterEscapes; import com.fasterxml.jackson.core.io.SerializedString; +import com.fasterxml.jackson.core.json.JsonReadFeature; /** * {@link com.fasterxml.jackson.core.TSFBuilder} * implementation for constructing vanilla {@link JsonFactory} - * instances. + * instances for reading/writing JSON encoded content. * - * @since 3.0 + * @since 2.10 */ public class JsonFactoryBuilder extends TSFBuilder { @@ -16,15 +17,67 @@ public class JsonFactoryBuilder extends TSFBuilder + * Since JSON specification does not mention comments as legal + * construct, + * this is a non-standard feature; however, in the wild + * this is extensively used. As such, feature is + * disabled by default for parsers and must be + * explicitly enabled. + */ + ALLOW_JAVA_COMMENTS(false, JsonParser.Feature.ALLOW_COMMENTS), + + /** + * Feature that determines whether parser will allow use + * of YAML comments, ones starting with '#' and continuing + * until the end of the line. This commenting style is common + * with scripting languages as well. + *

+ * Since JSON specification does not mention comments as legal + * construct, + * this is a non-standard feature. As such, feature is + * disabled by default for parsers and must be + * explicitly enabled. + */ + ALLOW_YAML_COMMENTS(false, JsonParser.Feature.ALLOW_YAML_COMMENTS), + + // // // Support for non-standard data format constructs: quoting/escaping + + /** + * Feature that determines whether parser will allow use + * of single quotes (apostrophe, character '\'') for + * quoting Strings (names and String values). If so, + * this is in addition to other acceptable markers. + * but not by JSON specification). + *

+ * Since JSON specification requires use of double quotes for + * field names, + * this is a non-standard feature, and as such disabled by default. + */ + ALLOW_SINGLE_QUOTES(false, JsonParser.Feature.ALLOW_SINGLE_QUOTES), + + /** + * Feature that determines whether parser will allow use + * of unquoted field names (which is allowed by Javascript, + * but not by JSON specification). + *

+ * Since JSON specification requires use of double quotes for + * field names, + * this is a non-standard feature, and as such disabled by default. + */ + ALLOW_UNQUOTED_FIELD_NAMES(false, JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES), + + /** + * Feature that determines whether parser will allow + * JSON Strings to contain unescaped control characters + * (ASCII characters with value less than 32, including + * tab and line feed characters) or not. + * If feature is set false, an exception is thrown if such a + * character is encountered. + *

+ * Since JSON specification requires quoting for all control characters, + * this is a non-standard feature, and as such disabled by default. + */ + ALLOW_UNESCAPED_CONTROL_CHARS(false, JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS), + + /** + * Feature that can be enabled to accept quoting of all character + * using backslash quoting mechanism: if not enabled, only characters + * that are explicitly listed by JSON specification can be thus + * escaped (see JSON spec for small list of these characters) + *

+ * Since JSON specification requires quoting for all control characters, + * this is a non-standard feature, and as such disabled by default. + */ + ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER(false, JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER), + + // // // Support for non-standard data format constructs: number representations + + /** + * Feature that determines whether parser will allow + * JSON integral numbers to start with additional (ignorable) + * zeroes (like: 000001). If enabled, no exception is thrown, and extra + * nulls are silently ignored (and not included in textual representation + * exposed via {@link JsonParser#getText}). + *

+ * Since JSON specification does not allow leading zeroes, + * this is a non-standard feature, and as such disabled by default. + */ + ALLOW_LEADING_ZEROS_FOR_NUMBERS(false, JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS), + + /** + * Feature that allows parser to recognize set of + * "Not-a-Number" (NaN) tokens as legal floating number + * values (similar to how many other data formats and + * programming language source code allows it). + * Specific subset contains values that + * XML Schema + * (see section 3.2.4.1, Lexical Representation) + * allows (tokens are quoted contents, not including quotes): + *

    + *
  • "INF" (for positive infinity), as well as alias of "Infinity" + *
  • "-INF" (for negative infinity), alias "-Infinity" + *
  • "NaN" (for other not-a-numbers, like result of division by zero) + *
+ *

+ * Since JSON specification does not allow use of such values, + * this is a non-standard feature, and as such disabled by default. + */ + ALLOW_NON_NUMERIC_NUMBERS(false, JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS), + + // // // Support for non-standard data format constructs: array/value separators + + /** + * Feature allows the support for "missing" values in a JSON array: missing + * value meaning sequence of two commas, without value in-between but only + * optional white space. + * Enabling this feature will expose "missing" values as {@link JsonToken#VALUE_NULL} + * tokens, which typically become Java nulls in arrays and {@link java.util.Collection} + * in data-binding. + *

+ * For example, enabling this feature will represent a JSON array ["value1",,"value3",] + * as ["value1", null, "value3", null] + *

+ * Since the JSON specification does not allow missing values this is a non-compliant JSON + * feature and is disabled by default. + */ + ALLOW_MISSING_VALUES(false, JsonParser.Feature.ALLOW_MISSING_VALUES), + + /** + * Feature that determines whether {@link JsonParser} will allow for a single trailing + * comma following the final value (in an Array) or member (in an Object). These commas + * will simply be ignored. + *

+ * For example, when this feature is enabled, [true,true,] is equivalent to + * [true, true] and {"a": true,} is equivalent to + * {"a": true}. + *

+ * When combined with ALLOW_MISSING_VALUES, this feature takes priority, and + * the final trailing comma in an array declaration does not imply a missing + * (null) value. For example, when both ALLOW_MISSING_VALUES + * and ALLOW_TRAILING_COMMA are enabled, [true,true,] is + * equivalent to [true, true], and [true,true,,] is equivalent to + * [true, true, null]. + *

+ * Since the JSON specification does not permit trailing commas, this is a non-standard + * feature, and as such disabled by default. + */ + ALLOW_TRAILING_COMMA(false, JsonParser.Feature.ALLOW_TRAILING_COMMA), + + // // // Support for non-standard data format constructs: JSON-like formats + + /** + * Feature that can be turned on to support handling of BSON "shell mode" JSON extensions + * as specified in {@link href="https://docs.mongodb.com/manual/reference/mongodb-extended-json/"}, + * for "shell mode" (but NOT "strict mode" which uses standard JSON syntax but additional + * structural constructs). + *

+ * NOTE: although attempt is made to support various extension wrappers there is no guarantee that + * all semantic aspects are retained for higher level processing. + * + * @since 2.10 + */ + HANDLE_BSON_WRAPPERS(false, null) + ; + + final private boolean _defaultState; + final private int _mask; + + /** + * For backwards compatibility we may need to map to one of existing {@link JsonParser.Feature}s; + * if so, this is the feature to enable/disable. + */ + final private JsonParser.Feature _mappedFeature; + + /** + * Method that calculates bit set (flags) of all features that + * are enabled by default. + */ + public static int collectDefaults() + { + int flags = 0; + for (JsonReadFeature f : values()) { + if (f.enabledByDefault()) { + flags |= f.getMask(); + } + } + return flags; + } + + private JsonReadFeature(boolean defaultState, + JsonParser.Feature mapTo) { + _defaultState = defaultState; + _mask = (1 << ordinal()); + _mappedFeature = mapTo; + } + + @Override + public boolean enabledByDefault() { return _defaultState; } + @Override + public int getMask() { return _mask; } + @Override + public boolean enabledIn(int flags) { return (flags & _mask) != 0; } + + public JsonParser.Feature mappedFeature() { return _mappedFeature; } +} diff --git a/src/test/java/com/fasterxml/jackson/core/json/async/AsyncTokenFilterTest.java b/src/test/java/com/fasterxml/jackson/core/json/async/AsyncTokenFilterTest.java index 8f9b7058bb..cdbf4252af 100644 --- a/src/test/java/com/fasterxml/jackson/core/json/async/AsyncTokenFilterTest.java +++ b/src/test/java/com/fasterxml/jackson/core/json/async/AsyncTokenFilterTest.java @@ -51,6 +51,7 @@ public void testFilteredNonBlockingParserAllContent() throws IOException public void testSkipChildrenFailOnSplit() throws IOException { NonBlockingJsonParser nbParser = (NonBlockingJsonParser) JSON_F.createNonBlockingByteArrayParser(); + @SuppressWarnings("resource") FilteringParserDelegate filteredParser = new FilteringParserDelegate(nbParser, TOKEN_FILTER, true, true); nbParser.feedInput(INPUT_BYTES, 0, 5);