dtolnay / serde-yaml

Strongly typed YAML library for Rust
Apache License 2.0
965 stars 164 forks source link

Yaml output indentation #337

Open jayvdb opened 2 years ago

jayvdb commented 2 years ago

I am using https://github.com/juhaku/utoipa 's to_yaml which uses serde_yaml::to_string, to generate a openapi 3 yaml file, and there is a lack of typical indentation in the output of arrays/sequences.

e.g.

openapi: 3.0.3
info:
  title: foobar
  description: Service to do blah ...
  contact:
    name: ''
  license:
    name: ''
  version: 0.1.0
paths:
  /my_endpoint_name:
    post:
      tags:
      - my_tag

Typical linters, e.g. https://pypi.org/project/yamllint/, require the - my_tag to be indented an extra two spaces. A lot of python cloud tools use yamllint, e.g. ansible-lint. More can be seen at https://www.wheelodex.org/projects/yamllint/rdepends/ , and that is just Python. https://developers.home-assistant.io/docs/documenting/yaml-style-guide/ is another style guide which expects that indentation.

I did a quick test against serde_yaml directly, and it looks like that the lack of indentation is the default. i.e. the following is true

let mut buffer = Vec::new();
let mut ser = serde_yaml::Serializer::new(&mut buffer);
let deserialized: BTreeMap<&str, Vec<&str>> = serde_yaml::from_str("k:\n  - a\n  - b\n  - c\n").unwrap();
deserialized.serialize(&mut ser).unwrap();
assert_eq!(buffer, b"k:\n- a\n- b\n- c\n");

i.e. the indentation is dropped.

It would be great if the default could be updated. And allow something like serde_json::PrettyFormatter::with_indent. It would also be handy to be able to specify other defaults, like whether strings should be enclosed in ' or " by default. I see something similar was asked in https://github.com/dtolnay/serde-yaml/issues/226

dtolnay commented 2 years ago

I would accept a PR to increase the indentation of sequence elements.

jayvdb commented 2 years ago

Looks like it might not be possible using libyaml https://github.com/yaml/libyaml/issues/224

jayvdb commented 2 years ago

fwiw, I was able to workaround this by pushing the yaml through a yaml-rust roundtrip, which defaults to the typical style of indentation in the output of sequences.

dtolnay commented 2 years ago

Which style does https://github.com/pantoniou/libfyaml do? If it works better we can switch from libyaml to libfyaml.

jayvdb commented 2 years ago

IMO it looks good. When I roundtrip yaml which has the desired indentation, forcing it into flow mode and then back to block mode, the desired indentation is restored. i.e. fy-tool --mode=flow in.yaml | fy-tool --mode=block > out.yaml; cmp in.yaml out.yaml :+1:

jayvdb commented 2 years ago

Anyone wanting to solve this with postprocessing on the CLI can use Rust tool https://github.com/xbcsmith/ymlfxr ; unfortunately not yet on crates.io - see https://github.com/xbcsmith/ymlfxr/issues/1 . (now fixed)