From c94cb960184c5b9c4b3260ade0f54c5d115e88eb Mon Sep 17 00:00:00 2001 From: HeikoBoettger Date: Sun, 21 Jul 2024 02:25:44 +0200 Subject: [PATCH] Allow passing `ParserImpl` by a subclass or overwrite the events (#482) Makes it possible to overwrite the getEvent calls on the parser to add additional functionality such as filtering, modifying and inserting events. Alternatively provide a constructor to allow using subclasses of the snake yaml ParserImpl. Note: didn't replace the internal parserImpl-field since other subclasses might already use it otherwise would make sense to use the Parser-interface instead. --- release-notes/CREDITS-2.x | 6 +++ release-notes/VERSION-2.x | 2 + .../jackson/dataformat/yaml/YAMLParser.java | 44 +++++++++++++++---- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index 61d57c37..6de6aae9 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -271,3 +271,9 @@ David Pujol (@PujolDavid) * Contributed #469: (csv) Allow CSV to differentiate between `null` and empty fields (foo,,bar vs. foo,"",bar) (2.18.0) + +Heiko Boettger (@HeikoBoettger) + +* Contributed #482: (yaml) Allow passing `ParserImpl` by a subclass or overwrite the events + (2.18.0) + diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index b3ef1a69..727c5415 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -21,6 +21,8 @@ Active Maintainers: #469: (csv) Allow CSV to differentiate between `null` and empty fields (foo,,bar vs. foo,"",bar) (contributed by David P) +#482: (yaml) Allow passing `ParserImpl` by a subclass or overwrite the events + (contributed by Heiko B) 2.17.2 (05-Jul-2024) diff --git a/yaml/src/main/java/com/fasterxml/jackson/dataformat/yaml/YAMLParser.java b/yaml/src/main/java/com/fasterxml/jackson/dataformat/yaml/YAMLParser.java index f85fa310..eed7a159 100644 --- a/yaml/src/main/java/com/fasterxml/jackson/dataformat/yaml/YAMLParser.java +++ b/yaml/src/main/java/com/fasterxml/jackson/dataformat/yaml/YAMLParser.java @@ -179,7 +179,6 @@ private Feature(boolean defaultState) { /********************************************************************** */ - /** * @deprecated since 2.14, use other constructor */ @@ -192,16 +191,28 @@ public YAMLParser(IOContext ctxt, BufferRecycler br, } public YAMLParser(IOContext ctxt, int parserFeatures, int formatFeatures, - LoaderOptions loaderOptions, ObjectCodec codec, Reader reader) + LoaderOptions loaderOptions, ObjectCodec codec, Reader reader) + { + this(ctxt, parserFeatures, formatFeatures, codec, reader, + new ParserImpl(new StreamReader(reader), + (loaderOptions == null) ? new LoaderOptions() : loaderOptions)); + } + + /** + * Constructor to overload by custom parser sub-classes that want to replace + * {@link ParserImpl} passed. + * + * @since 2.18 + */ + protected YAMLParser(IOContext ctxt, int parserFeatures, int formatFeatures, + ObjectCodec codec, Reader reader, + ParserImpl yamlParser) { super(ctxt, parserFeatures); _objectCodec = codec; _formatFeatures = formatFeatures; _reader = reader; - if (loaderOptions == null) { - loaderOptions = new LoaderOptions(); - } - _yamlParser = new ParserImpl(new StreamReader(reader), loaderOptions); + _yamlParser = yamlParser; _cfgEmptyStringsToNull = Feature.EMPTY_STRING_AS_NULL.enabledIn(formatFeatures); } @@ -294,8 +305,10 @@ protected void _closeInput() throws IOException { * Reader (granted, we only do that for UTF-32...) this * means that buffer recycling won't work correctly. */ - if (_ioContext.isResourceManaged() || isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)) { - _reader.close(); + if (_reader != null) { + if (_ioContext.isResourceManaged() || isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)) { + _reader.close(); + } } } @@ -434,7 +447,7 @@ public JsonToken nextToken() throws IOException while (true) { Event evt; try { - evt = _yamlParser.getEvent(); + evt = getEvent(); } catch (org.yaml.snakeyaml.error.YAMLException e) { if (e instanceof org.yaml.snakeyaml.error.MarkedYAMLException) { throw com.fasterxml.jackson.dataformat.yaml.snakeyaml.error.MarkedYAMLException.from @@ -564,6 +577,19 @@ public JsonToken nextToken() throws IOException } } + /** + * Since the parserImpl cannot be replaced allow subclasses to at least be able to + * influence the events being consumed. + * + * A particular use case is working around the lack of anchor and alias support to + * emit additional events. + * + * @since 2.18 + */ + protected Event getEvent() { + return _yamlParser.getEvent(); + } + protected JsonToken _decodeScalar(ScalarEvent scalar) throws IOException { String value = scalar.getValue();