Increase simple key length to 1024 stream characters

Issue #431 resolved
Sergey Leonov created an issue

Version

SnakeYAML 1.23, Java 1.8.0_181

Problem

Accordingly to https://yaml.org/spec/1.1/#id934537, the simple key must not span more than 1024 stream characters while now it is limited to just 128 characters, which causes the output to be broken on valid input data.

Reproducing the problem

Building YAML out of the Spring MVC controllers using springfox, jackson, and snakeyaml. One of the REST methods has 13 query parameters, and the displayed name has the length of 160+ symbols.

Expected output

paths:
  /examples/{exampleId}/example/example{?exmplType,exm,exmplsOnly,examplea,exmplFrom,exmplTo,exmplLimit,exmplLocal,exmplRequest,exmpls,exampleb,exmplTypes,examplec}:
    get:
      tags:

Actual output (broken)

paths:
  ? /examples/{exampleId}/example/example{?exmplType,exm,exmplsOnly,examplea,exmplFrom,exmplTo,exmplLimit,exmplLocal,exmplRequest,exmpls,exampleb,exmplTypes,examplec}
  : get:
      tags:

Proposed solution

Increase the limit to 1024 characters here, preferably making a constant out of the hardcoded value:

https://bitbucket.org/asomov/snakeyaml/src/0f5a5ee9fae1c50f75ebbcb218f68cc2dc012542/src/main/java/org/yaml/snakeyaml/emitter/Emitter.java?at=default&fileviewer=file-view-default#Emitter.java-706

Comments (14)

  1. Andrey Somov

    Sorry, my fault. I was too quick with my conclusion. This is not a question of specification but a flavour of SnakeYAML to decide when to use simple key.

    It will require to change the DumperOptions to introduce a setting to customize the length.

  2. Andrey Somov

    Please be aware that the output is not "broken" as indicated above. It is a valid YAML but the key is explicit.

  3. Sergey Leonov reporter

    Thank you Andrey! I've created a sample project, however it seems to be useless now.

  4. Sergey Leonov reporter

    I've attached the demo app. For now I have no idea how to proxy the newly introduced DumperOption from the Spring config when the YamlFactory is created.

  5. Andrey Somov

    As far as I know they use Jackson, which means that you need to ask Jackson community to accept another setting:

        public YAMLGenerator(IOContext ctxt, int jsonFeatures, int yamlFeatures, ObjectCodec codec, Writer out, Version version) throws IOException {
            super(jsonFeatures, codec);
            this._ioContext = ctxt;
            this._formatFeatures = yamlFeatures;
            this._writer = out;
            this._outputOptions = this.buildDumperOptions(jsonFeatures, yamlFeatures, version);
            this._emitter = new Emitter(this._writer, this._outputOptions);
            this._emitter.emit(new StreamStartEvent((Mark)null, (Mark)null));
            Map<String, String> noTags = Collections.emptyMap();
            boolean startMarker = YAMLGenerator.Feature.WRITE_DOC_START_MARKER.enabledIn(yamlFeatures);
            this._emitter.emit(new DocumentStartEvent((Mark)null, (Mark)null, startMarker, version, noTags));
        }
    
  6. Sergey Leonov reporter

    Looks like this method in YAMLGenerator is the subject to change:

        protected DumperOptions buildDumperOptions(int jsonFeatures, int yamlFeatures, org.yaml.snakeyaml.DumperOptions.Version version)
        {
            DumperOptions opt = new DumperOptions();
            // would we want canonical?
            if (Feature.CANONICAL_OUTPUT.enabledIn(_formatFeatures)) {
                opt.setCanonical(true);
            } else {
                opt.setCanonical(false);
                // if not, MUST specify flow styles
                opt.setDefaultFlowStyle(FlowStyle.BLOCK);
            }
            // [dataformat#35]: split-lines for text blocks?
            opt.setSplitLines(Feature.SPLIT_LINES.enabledIn(_formatFeatures));
            return opt;
        }
    
  7. Log in to comment