366 comments

[ 0.19 ms ] story [ 346 ms ] thread
What are the practical modern alternatives for YAML use cased? TOML, others?
TOML is good for simple plain structures. As soon as you have more nested structures, you can also use json.
For simple use cases like key-value style config you can use JSON or TOML without too many issues.

For IaC the alternative is general purpose programming languages using declarative infrastructure APIs. E.g. TS, Go, Python with CDK, CDKTF, Pulumi. For CI are stuck with YAML for now.

People often forget about the environment, and I feel like a lot of the simpler services and applications could be configured through it easily.

For anything that requires more complex structures, JSON5 (https://json5.org/) has been gaining traction. It's basically JSON that allows a couple of more things, including comments, trailing commas, and even unquoted keys, if you're into that.

This for this it indeed looks very much better than json or yaml.
edn

Extensible Data Notation, it's to Clojure what json is to Javascript.

As another top-level comment mentions, one alternative is NestedText, where everything is a string unless the ingesting code says otherwise, and there is no escaping needed at all.
TLDR: unexpected conversions to other types in YAML 1.1.

A larger JSON document is hell to write and read, though.

(comment deleted)
JSON is arguably much worse for usage in Git. Have fun matching braces in the default diff tools out in the wild.

YAML is the much better alternative with similar semantics to JSON. The numeric issues still hold true though.

Isn't TOML just the .INI files of yore? At least it looks very similar.
The feature set of toml is similar to json, but with ini like syntax.

Most significantly ini-files have a fixed two level structure (section -> key -> value) while toml supports arbitrary nested arrays and dictionaries.

And don't forget one of the more understated benefits of TOML over INI:

> A TOML file must be a valid UTF-8 encoded Unicode document.

Is there a tool that parses yaml and outputs json, so you could check if the yaml you wrote parses as you intent?
This is not claimed by the article afaict. It's stated though that json spec/syntax is simple, and that it's simple as a language; my interpretation is that this means "simple/understandable/predictable for humans".
I was at a place 7-8 years ago with a hand-rolled JSON parser that had been written across a few afternoons by one guy without much ceremony. It was untouched after that aside from some renaming and other minor refactors. As usual with these things, the decision to hand-roll was made by one very opinionated dev who got his way because the business depended on him.

When that article was published it started an argument among the team. The guy ended up implementing the test suite to defend his decision. To my surprise the parser passed all tests apart from 3 or 4 unicodey-ones where it was more permissive than it should have been. There were plenty of production bugs at this place but none of them were due to the parser.

IMO parsing JSON really is simple. If you read through the article you'll see that most of the test cases are dead simple and hardly landmines.

JSON is a subset of YAML. (you can just dump JSON in your YAML document and it’s a valid YAML.)

So parsing YAML will be strictly harder, as it needs to include a JSON parser.

If language A is a subset of language B it doesn't follow that parsing B is strictly harder.

This is not guaranteed. Consider two languages:

1. Some number of "a" followed by the same number of "b". For example, aaabbb but not aabbb.

2. Any number of "a" followed by any number of "b". For example, aabbb but not aba.

In this case (1) is a subset of (2), but parsing (2) is easier than parsing (1) since in (1) you have to verify that the numbers match (which, in technical terms, means its not regular).

This is why I invented KYLI - https://shkspr.mobi/blog/2017/03/kyli-because-it-is-superior...

People shouldn't be hand-editing these sorts of configuration documents. 21st century tooling would prevent so many of these "foot-guns".

This one liners lead to unreadable configuration. With tools, the format is not important. But we did not talk about tools, we talk about that humans can easy read and write a configuration.
A text editor is a tool. Text files are only "human readable"/"human editable" in the sense that such tools are ubiquitous whereas structured data editors are not.

Which is a real shame. Entering, manipulating and validating small amounts of structured data is such a fundamental task when using computers that it deserves dedicated tools, and the sheer amount of issues that only exist because such tools are not ubiquitous is absolutely mindboggling.

> There were two changes to it in 2005 (the removal of comments, and the addition of scientific notation for numbers)

They actually had comments in JSON but removed them in 2005. That is odd and a bit annoying :-)

What we need is some kind of extensible markup language ...
Funny but not quite.

Nobody wants extensibility and "document markup" isn't the same as "configuration specification"

> is that for a long time it was the only viable configuration format

Actually, this is not the case. We had INI format for simple stuff and XML (protected with entire schema) for complex things many years ago, which worked. Yet, we wanted something readable (like INI), but able to express complex types (XML).

I don't think Toml is a viable replacement - for me, it has an INI-level of simplicity with even worst hacks to have nested structures. But, give it time and you'll have another YAML.

But yes, YAML is confusing for edge cases (true/false, quoting), but I'm going to find a powerful replacement that is not XML. Maybe EDN can jump in, but for anything more complex, I'd rather have a Lisp interpreter and structures around than any of mentioned and upcoming formats.

Thinking that JSON is a suitable replacement, imagine writing Ansible or k8s stuff in it; that would be fun ;)

> Thinking that JSON is a suitable replacement, imagine writing Ansible or k8s stuff in it; that would be fun ;)

Writing in YAML doesn't feel much better. YMMV but I've been on teams using Pulumi for k8s and the developer experience has been significantly better. I can automate, type check, lint, click through to definitions the same way I do with other typescript.

Pulumi is a young product with many rough edges but it's already been a game changer for me.

It's very simple actually.

... just fucking don't, generate config in your configuration management tool of choice and then serialize it to YAML. You get all of the advantages (nice to read)and none of the disadvantages (need editor or it is PITA)

I checked the sample Kubernetes project in Java [0] and it looks hideous. YAML looks much better in comparison.

[0] https://www.pulumi.com/docs/get-started/kubernetes/review-pr...

Don't disagree there. Java support is less than a year old and the Java API is.. not great. TypeScript is the more popular and mature choice.
What, you mean you don't want to write code like

  Deployment("nginx",DeploymentArgs.builder().spec(DeploymentSpecArgs.builder().selector(LabelSelectorArgs.builder().matchLabels(labels).build()).replicas(1).template(PodTemplateSpecArgs.builder().metadata(ObjectMetaArgs.builder().labels(labels).build()).spec(PodSpecArgs.builder().containers(ContainerArgs.builder().name("nginx").image("nginx").ports(ContainerPortArgs.builder().containerPort(80).build()).build()).build()).build()).build()).build());
I actually laughed out loud when I looked at the example and just saw a bunch of carefully-indented “.build()”s
I would love to swap Pulumi for Ansible, but it's cloud-only for the most part.
JSON has no comments. That disqualifies it immediately.

    {
        “/*These are the ports we use”: “*/”,
        “ports”: [22, 80, 443]
    }
Now, write a json-schema for that.
Can be done by either additionalProperties: true and not specifying the property, or "patternProperties": { "^/\*": { "type": "string" }}.
I'd rather have real comments than this epicycle.
"additionalProperties": true
“Comment”: ”This is a comment that is optional and ignored by code”
"Comment": "but you can only have one per object"
"Comment1": "This is the first comment"

"Comment2": "This is the next comment"

or

"Comments": ["Here is one", "Here is another!"]

or

"Comments": { "Name": "This is the name of the customer", "Age": "This is the age (0 to 1000) of the customer" }

or

"Values": [ {"Name":"Age", "Value":"20", "Comment":"This is the age of the customer"}, {"Name":"Name", "Value":"Mr. Foo Bar", "Comment":"This is the name of the customer"} ]

The only limit is your imagination.

Many JSON dialects do in practice.
Use S-Expressions?
With each tool using its own macro-based DSL for managing them. That would be fun
S-expressions do not necessarily imply Lisp nor an executable environment, it's a (family of) syntax(es) to build a document format. Like EDN.
So even worse as you can't use any prior knowledge of lisp
I know what s-expressions are, vaguely. Vaguely in terms of "I couldn't write a grammar for them off the top of my head.", that is, not "what are they".

Is there a single agreed-upon defined grammar that everyone can use? Preferably one simple enough that like JSON's it is at least capable of being used as a graphic on the home page for the format? https://www.json.org/json-en.html

This is an honest question, because there may well be and I don't know it.

However, I will put this marker down in advance: If multiple people jump up to say "oh, yes, of course, it's right here", and their answers are not 100% compatible with each other, then the answer is no.

The other marker I'll put down is "just use common lisp", I want verification that it really is 100% standardized, no question what any construct means, ever, and I still bet we get people who would rather see Scheme or Clojure, and I bet there's some sort of difference.

Neither of these objections is fatal to the idea. JSON is technically not just "javascript objects", so if someone carved out a defined format from s-expressions, then held it up as a standard, that would be as valid as what Crockford did. But at least as of right now, I'm not aware of anyone having done that standardization work. Replies welcome.

  SEXPR := YOUR-CUSTOM-LITERALS
         | "(" SEXPR* ")"
Along with the many other issues that would have for just straight-up not being a usable grammar, the word "CUSTOM" appearing in a nominal cross language standard is a non-starter.
Oh come on. Did you think anybody would write an RFC in the comments? Add arbitrary list of whitespace tokens everywhere and pick whatever favorite grammar you have for literals. Json strings and numbers since you seem to like them.
Of course not. But you are at least semi-seriously trying to propose something. I promise you it won't be that easy to get any sort of agreement.

This is a classic "oh come on how hard can it be" that, once you get into it, it turns out the answer is very. Arbitrarily so. Agreement is hard. Details are hard. A standard with no details is not terribly different from "just give us some text".

I don't see a grammar I could use for an external standard there. I could be missing it. And I assume there must be one implied, since it appears to be a read-write format. However such things have a nasty habit of turning out upon further inspection to not be as generic as supposed and have local idioms buried in them, often in surprising places. Even JSON, simple as it is, had that problem, and it is after all a subset in an attempt to squeeze out those localisms.

Is it compatible with Common Lisp, such that all such s-expressions will be compatible with it in some natural way?

Well, I would have suggested Racket. Common Lisp is a bit ugly, both conceptually and syntax-wise.
My distaste for yaml led me to attempt just that. The first piece that was missing for me was a python parser that could produce reasonable error messages and could be transformed into the desired internal representation in python. So I wrote one [0]. It was supposed to be a single file that was less than 100 lines and could be copied and pasted into any project that I needed. Turns out that the issue was a bit more complex.

The issue is that there is sufficient complexity in finding a portable representation for configuration formats that it just kicks the can down the road. On the other hand it means that as soon as you decide what format you are going to support you can quickly implement it. There is more or less a intersectional grammar that works across most if not all lisps, and that is the plist `(:k v :k2 (:k3 v2))`. So I settled on that for my own use.

After all that work I have not dealt with the fact that numbers and chars do not have a portable representation across lisp dialects, which is a key complaint in other threads here. Limited support for let binding constants also seems like a feature that would allow for just enough expressivity to make the format useful without opening up the terror that is `&` and `*` in yaml (cool and useful as it may be).

In summary s-expressions are: 1. missing good parsers in a number of language ecosystems 2. not standard across lisp dialects 3. need additional semantics for binding, multiple expressions, etc. 4. still better than yaml and json

0. https://github.com/tgbugs/sxpyr

> YAML is confusing for edge cases (true/false, quoting)

I'm not sure I would consider booleans an 'edge case'

Booleans aren't an edge case, on is an edge case way to spell false.
specifically according to https://yaml.org/type/bool.html:

     y|Y|yes|Yes|YES|n|N|no|No|NO
    |true|True|TRUE|false|False|FALSE
    |on|On|ON|off|Off|OFF
Not all parsers support all of these options, but true|false is always supported as YAML is a superset of JSON which makes these mandatory.
I can't imagine thinking this is a good idea if you've done any programming whatsoever. What happened here?
If you aim to be "human-friendly" (and that is, as I understand, the raison d'etre for YAML), there is a subtle semantic difference between "true" and "on" (and "false" and "off") and as a human it may be nice to express that semantic difference.

As for that semantic difference, if we expect the light source to have one of exactly two states (that is, "not a dimmable light"), we probably want to express that as "lightsource: on" rather than "lightsource: true".

And that is where the friction between "humanfriendly" and "computer-friendly" starts being problematic. Computer-to-computer protocols should be painfully strict and non-ambiguous, human-to-computer should be as adapted as they can to humans, erring on "expressive" rather than "strict".

I am also not sure if I am happy or sad that the set of configuration languages in the original article didn't include Flabbergast[1], which was heavily inspired by what may be simultaneously the best and worst configuration language I have seen, BCL (a language that I once was very relieved to never have to see again, and nine months later missed so INCREDIBLY much, because all the other ones are sadly more horrible).

[1] https://www.flabbergast.org/

Even leaving aside the word <on>, it's problematic that, syntactically, <true> and <foobar> look the same but are treated differently.
Its something of a tradeoff space that is always there you either have things that look the same be implicit (eg is 1 and 10000000 the same type? How about 1 and 1. ? How about 1 and -1?, how about 1 and moo? 1e2 and 1f2?

You can have things be explicit and verbose (have explicit unambiguous identifiers on every value), or you can have things magic and then surprising in something like this.

Rails also made a similar decision to basically auto convert what would be the string true to the Boolean value true in many cases. It's not obviously right or wrong, it's just a choice that has tradeoffs.

I think my own sensibility is that it's actually reasonable for something like yaml to allow you to choose to omit quotes and if you do then it's automatic typing: 1e2 is a number and 1z2 is a string. If you want it to be a string you can put quotes on every value if you want, exactly like you would in json, choosing unquoted for things that are strings is choosing the automatic typing case.

But these other values like y and n being autotyped as bool are suspect autotype behavior to me: even once you've accepted unquoted is autotyped you are more likely to be caught off guard by this than by 0 vs true vs 0z.

I'm nose deep in an Oracle to Postgres conversion at the moment and from that experience, among others, I can absolutely assure you that although booleans are definitely simple they are also most definitely a very sharp edge case.
But who doesn't love the OracleDB tri-state boolean?

/s

Booleans, or NULL specifically?
yes (in oracle - at least the early 21st century version I'm using you have to roll your own boolean-ish - traditionally char(1).
The "edge case" here is "I'm using dynamically typed language and some parsers implemented alternative wording for true/false"
It was a part of the YAML spec for a long time, so it has nothing to do with dynamic typing or parser extensions.
It does. If I define struct to contain boolean, Go yaml parser will always parse it to boolean

If I define it as any other type, it will parse it as that type. So any conflicts like in the article just don't happen, or at worst, produce error in parsing.

Static typing in this case acts essentially as schema

Jsonnet and Cue are the places to be looking.
Cue is one of the most exciting developments that's impacted me professionally in recent years. I can't advocate for it enough.
Cue is interesting, but why is it only available as a command-line tool rather than a library? I'd want to integrate such a configuration language in my programs, so I could use its evaluation and validation capabilities rather than writing a custom parser/validator.
Also their website is terrible. One of those projects that assumes you've already decided (or been forced) to use it and have cleared out a week of your schedule to learn how to use it.
I learned cue from it during one weekend with plenty of time to play with kids, using it in production since 2020, it's been absolutely great, zero problems, very terse configs, intuitive formalism.
I took another look and eventually found the bit of the website that they should put front and centre in the Tutorial page. Still difficult to navigate (why doesn't the page tree show up on the left?) but it is at least well written and to the point.

The "learn more" button on the front page should link to that, perhaps with a single paragraph giving motivation.

And the main page breaks the fundamental rule of programming languages/formats. Put examples on the front page!

I assumed they hadn't done that because the examples would be too complex or maybe the concepts were too difficult to demonstrate with small examples but having gone through the tutorial that isn't there case at all.

Are you talking about https://cuelang.org/docs/tutorials/tour/intro/ ? Even that is a bit light on detail for real usage, while https://github.com/cue-lang/cue/blob/v0.4.3/doc/tutorial/kub... is kinda rambling. I don't think that there's "One true way" to introduce these concepts; How you teach cue to a config-generation novice is very different from someone who's used to using an IDE to generate kubernetes YAML.
Spec [0] is very good + practice with small files.

[0] https://cuelang.org/docs/references/spec

I find specs nearly unreadable when trying to first digest a language; While invaluable for advanced usage and implementation, I can't read a BNF-Style Spec and make heads or tails of what's going on unless I also have an annotated example next to it.
I agree. The website is heavy on theory and very light on practical usage.
If you're writing in Go, you can use it as a library. This is poorly documented, unfortunately.
INI has no spec, and there are many variations all slightly incompatible with each other, kinda like Markdown. YAML is really the only sane configuration language that lets you denote nested structures while keeping them look nested.

Basically, all of the problem identified in the article can be dealt with 1 rule - always quote your strings. I agree with the author we should have reduced, safe and minimalist subset of yaml, which is basically YAML 1.2, released in 2009.

P.S. Please just stop using PyYAML.

> Please just stop using PyYAML.

Why?

From the article:

  Although yaml 1.2 is more than 10 years old by now, you would be mistaken to think that it is widely supported: the latest version libyaml at the time of writing (which is used among others by PyYAML) implements yaml 1.1 and parses 22:22 as 1342.
I second that. And if people need to deal with YAML in Python, they should be using ruamel.yaml, which is a far superior library on just about every level: https://pypi.org/project/ruamel.yaml/
Except that the author of ruamel.yaml:

refuses to use git [0]

refuses to take community submissions (except through Stack Overflow? Seems like a misuse of SO) [1]

and refuses to implement .dumps() [2].

He is difficult to work with, and any time I need to debug code that intimately deals with ruamel.yaml types, I wince.

[0] https://github.com/pycontribs/ruyaml/issues/1

[1] https://yaml.readthedocs.io/en/latest/contributing.html

[2] https://stackoverflow.com/a/63179923/15170511

Why would I care that the maintainer prefers Mercurial? The document you linked to doesn't say anything about them not taking community submissions: I think you need to scroll down further in the page. And it certainly doesn't say that you have to use SO to submit changes.
There's HOCON which is pretty good if you can run on a JVM. It's a superset of JSON designed for readability and human-friendliness when writing config files. It doesn't change the type system and doesn't have yamls weird edge cases, but is still a lot easier to write than JSON. There's also a relatively tight spec.

https://github.com/lightbend/config/blob/main/HOCON.md

We use an extended version of it for our app and the resulting config is pretty clean. You can see an example here:

https://hydraulic.software/blog/8-packaging-electron-apps.ht...

The only downside is that the reference implementation is hardly maintained anymore.

> Thinking that JSON is a suitable replacement, imagine writing Ansible or k8s stuff in it; that would be fun ;)

k8s via helm is often templated via go template strings; which works by creating an unreadable and unhighightable mess, introducing lots of its own bugs.

XML did everything and it's perfectly readable if it's formatted and structured well. This zoo of different markup/object/whatever languages we have to deal with now is largely a mistake.
XML is too much of a pain to write by hand.
XML is like violence. If it’s not solving your problem, you need to use more
It’s not that bad really. About the same as HTML, yet more difficult to mess up.

Has comments, unlike JSON.

More difficult to mess up than YAML.

XML is pretty tolerable with a slightly more sophisticated editor that supports completion. The things that make YAML awful never get any better.
Throw in copilot to anticipate all the boilerplate and repetition for you and it's downright pleasant.
XML is a mistake. 80% of every XML document is just redundant noise because the IBM lawyer who invented the SGML syntax had never heard of S-expression.
SGML is way shorter than XML.

But as complex as YAML to understand

The "redundant" noise makes it more human-readable in my opinion. If you're in the weeds of a big XML document that's larger than your viewport, being able to see that you're at the end of a </Address> helps you keep your place, as opposed to something like JSON which I find much easier to get lost in. Even if it's not that big I appreciate the extra rails on the XML making it easier to keep my place.
I consider this a fallacy. The condition you are given is not a common occurence. In the event they do occur, the solution can be found in your editor or viewer. It does not make sense to inject spurious junk into what is designed as a data interchange format, in which includes network information interchange.

There's probably a name for this kind of fallacy that exaggerate the effect of a problem and the resulting contortions that were engineered around it.

Writing documents with S-exprs will get very tedious once you have to deal with stuff like whitespace and such that will inevitably show up when you're dealing with text documents. SGML is specifically optimized for those use cases, which is why it is so much more awkward to use when all you want is serializing some random structured data.
All you need is some sort of Python’s raw string or triple quote or HEREDOC. What’s so hard about that?
Try writing a document that's mostly text, but with plenty of markup interspersed in the middle, in this manner.
We are talking about a configuration language here, which is never about markups. Also, most of the so-called whitespace problem in Ansible or k8 configs comes from embedding config that's not YAML. In these cases you need a path or URI for the processor to resolve before applying, not inverting the entire configuration language to cater to 1 uncommon use case.
The point of my original comment was precisely that SGML was optimized for text documents. I agree that adopting it for configs was a mistake, but the complaint that "IBM lawyer who invented the SGML syntax had never heard of S-expression" doesn't make any sense in that context.
This is confusing because XML is the archetype of what I would consider unreadable. If I got a prompt in a programming language design workshop to intentionally design something unreadable for humans, I would start thinking about XML and see where it leads me. Can you name any language any more unreadable than XML to help me?
https://www.mssqltips.com/tipimages2/2899_img5.jpg

I look at this and I see a visually-well-organized hierarchy of objects with properties and children. It's a sideways tree diagram. I honestly don't get what's supposed to be unappealing about it.

> Can you name any language any more unreadable than XML to help me?

Most of the other markup languages depending on the usecase. The "redundant" tags everywhere like </Address> in XML are very helpful if you're in the weeds of a big document that's taller than your viewport - you still know exactly what you're looking at and where in the hierarchy you are, as opposed to JSON or YAML which I find much easier to get lost in.

Anyone can pick up a (properly-named) XML document and tell what it means at a glance, but JSON is easily a mystery unless you know the implicit schema beforehand.

Maybe there's some minor friction to get past looking at XML because it's a little visually busy before you learn how to parse it out? Is that all there is to it?

I understand where you’re coming from because it’s true XML is going to perform the functions required without all the problems implicit with YAML’s “readable” syntax…

But I have worked with some very complex XML and I feel you’ve chosen a simpler to read example.

I have seen very complicated XML from Microsoft’s own configurations that is so large, long, and complicated that it is very hard to follow

If JSON and YAML were first on the scene; XML would be invented as an answer.

Hard to mess up. Robust schema language. Very flexible. Easy to process.

Yeah, it’s verbose, but that’s the trade-off between usability and robustness.

Now get off my lawn!

What XML replaced was a combination of custom designed (often binary) formats and HTTP query-string like syntaxes. It is quite verbose compared to either of them, and explodes both your bandwidth and serialize/deserialize times, but it is arguably easier for your new co-worker to guess that the address line 2 goes in <address2>...</address2> rather than prefix tagged with 13, or worse yet at offset 42-61.

I got used to XML, tho I never could quite understand XSLT and the desire to program in it. I got used to json, but yaml I just can't bring myself to parse. YAML is 90% stuff you can't guess and just 10% data. And why so many?

No. XML is broken for structured data that isn't HTML because it's not really clear (there aren't even "best practices" afaict) what should be a text node, what should be an attribute node, and what should be a subtag node.
It's not like other formats don't face similar questions. E.g. if you have a list of key-value pairs to serialize to JSON, do you translate those keys to JSON properties in an object, or do you translate each pair as an object in an array?
The motivation for doing that in JSON comes with best practices: you use the key-value objects thing if and only if you have an ad-hoc list of items that you'd really really like to shove into a well-typed schema.
JSON is good because it doesn't let you do stupid things like writing programming languages in it.
Is INI a format in the sense that it has a formal grammar and a bunch of compatible parsers and serializers, or is it more of a convention?
Almost all those problems are solved by marking up the strings as strings, using " and ".
Then they should make quotes necessary in the YAML-specification. Little more to write, but better to validate.
I agree. They make a rod for their own back by having implicit conversion rules which, while well defined, are not well understood. "Explicit is better than implicit" and all that.
Advantage: things like "literal_block: |" or ">" are not necessary with a simple quote.

And i really don't know, why in hell they add binary-Data to a configuration language for humans.

Great idea. I would also suggest adding some syntax to make lists and maps more obvious (it can be a bit unclear in YAML). Maybe {} for maps and [] for lists.
My wish for a dream config language is this: Allow a choice between unambiguously-typed expressions (quoted strings, only true/false, decimal numbers) and explicit type annotations. So this:

    regions: $[string]
      - no
      - se
    options: ${bool}
      a: yes
      b: no
(with possibly a different syntax) would be equivalent to

    regions:
      - "no"
      - "se"
    options:
      a: true
      b: false
No, all the problems are solved by this.

It’s really no wonder that it’s hard to create a language that’s supposed to know whether the author intended to write a string or not without it being indicated by the syntax. No other language in the world tries to do this, for exactly the reasons this article points out.

(comment deleted)
(comment deleted)
Ansible collection writer here, pray for me...
I've never met anyone who say's "I like YAML, it is great"... most people that worked with it say something like "YAML is annoying, I don't like it"...

While introducing Kubernetes at our company in the last two years, we are currently in a process going more and more away from YAML with internal Helm charts to a much simpler process by just using HCL and Terraform, and defining Kuberentes resources as Terraform resources.

As a software developer HCL just makes so much more sense than this YAML + Helm + Go templates hell, which feels like C preprocessor hell all over again. Other solutions like kustomize are neat, but I don't see how all of these YAML workarounds should be better than something like HCL with Terraform. HCL feels like a real declarative programming language (with real conditions, variables, a module system and useful built-in functions). YAML feels like another more complex JSON and other tools like Helm or Kustomize try to work around the weaknesses of YAML with some kind of templating system.

YAML looks nice to read in simple demos and in small files, but is just not adequate in the real world (in my personal opinion - I know that YAML is used by a lot of people in production as of today).

Yup exactly my experience as well, again a stupid idea to try and make a "configuration" language out of nested key value pairs that end up needing fancy interpreters allowing more and more semantic into the keys and values to start doing what a simple program could have done in half the time...

I ve worked in 4 companies over a period of 10 years, each had exactly this problem, with yml, json, xml, properties file (you dont want to see business logic conditionals in a properties text file, where the keys shapes command an interpreter to behave dynamically...)

The only times I saw a team do it well was a php backend of all things where the lead said they d program all their variations in php rather than source it from configuration flat descriptors and it was amazing, clear, simple and powerful. They had to release the backend at each config change instead of releasing the config change only, but Im still unsure why exactly that's a problem: the configs are software too if we re honest with ourselves, shoe-horning them in a descriptor language isnt gonna make them flat.

The problem is mixing data with logic. I cannot imagine how maintainable a small program becomes when this concept is employed, much less a big one.
I like YAML. More specifically, the subset of YAML, like the author suggests. Clear, intuitive, and allows expressing of complex data structures like JSON does. Much better than TOML, which easily becomes a mess with more complex data.
Yeah. My headcanon YAML is amazing.
I like YAML.

I like that you can use anchors and merges. It greatly simplifies complex, repetive structures. And most of the complaints about yaml can be worked around by string-quoting.

The whitespace can get in the way if you're templating, but then you can also use [1, 2, 3] as a list notation, for example.

In fact, most of the complaints could be resolved by running it through a linter.

> I've never met anyone who say's "I like YAML, it is great"

Maybe I'm older than you, but I have definitely heard that line.

Mostly because the alternatives were XML, INI or the myriad of bespoke formats, relayd/apachehttpd .conf or iptables etc;etc;

INI has parsers that operate in different ways and doesn't support heirarchies... so that's not ideal.

JSON and YAML came to the fore around the same time, and JSONs limitations in comments and it's picky semantics meant that people did prefer YAML over JSON for human readable configs.

YAML itself is fine, it has some really awkward warts and the parsers are usually programatically unsafe in their implementation (leading to less compatible "safe_load" or other types of loaders)[0]; the issue we actually have with YAML is that we:

A) Template it (jinja, mustache whatever)

B) Put entirely too much stuff into it. (kubernetes manfiests can grow to the hundreds of lines really easily)

These problems will affect any configuration file format we choose to use, including TOML (which is comparatively new on the block), because reading templated/enormous files is really difficult.

What I've taken to doing is programatically generating objects and then serialising them as whatever my software depends on. It might feel ugly to use an entire turing complete language to generate objects that are mostly static: but honestly... the ability to breakpoint, test and print the subsections of output is astonishingly nice.

Then I don't care at all what the format is.

[0]: https://www.serendipidata.com/posts/safe-api-design-and-pyya...

I kinda miss XML. Yeah, I'm weird.

The tooling is super mature, it's easy to emit, it's easy to parse, it's easy to validate, it can just a little hard to read and write by hand (and I mostly blame SOAP for that). Still, basic XML isn't that hard to read or write, thanks to editor support.

I still wouldn't want to read this, and this is a simple example. :\

    <apiVersion>apps/v1</apiVersion>
    <kind>Deployment</kind>
    <metadata>
      <name>
        some-deployment
      </name>
      <namespace>
        deployment-namespace
      </namespace>
    </metadata>
    <spec>
      <replicas>1</replicas>
      <revisionHistoryLimit>3</revisionHistoryLimit>
      <selector>
        <matchLabels>
          <app>
            some
          </app>
        </matchLabels>
      </selector>
      <template>
        <metadata>
          <labels>
            <app>
              some
            </app>
          </labels>
        </metadata>
        <spec>
          <serviceAccountName>dbuser</serviceAccountName>
          <nodeSelector>
            <iam.gke.io/gke-metadata-server-enabled>true</iam.gke.io/gke-metadata-server-enabled>
          </nodeSelector>
          <imagePullSecrets>
            <name>dckr-auth</name>
          </imagePullSecrets>
          <containers>
            <name>
              some-service-container
            </name>
            <image>
              dckr.io/some/deploymentImage:latest
            </image>
            <imagePullPolicy>Always</imagePullPolicy>
            <ports>
              <containerPort>8000</containerPort>
            </ports>
            <env>
              <name>DB_URL</name>
              <value>postgresql://pgsql%40{{.Env.GCP_PROJECT_ID}}.iam@127.0.0.1:5432/{{.Env.NAMESPACE}}-{{.Env.SERVICE | strings.TrimSuffix "-service"}}</value>
            </env>
            <env>
              <name>LOGGING_LEVEL</name>
              <value>debug</value>
            </env>
            <env>
              <name>TRACING_ENABLED</name>
              <value>false</value>
            </env>
            <env>
              <name>APP_NAME</name>
              <value>
                some
              </value>
            </env>
            <env>
              <name>AUTH_URL</name>
              <value>http://auth/auth</value>
            </env>
            <env>
              <name>KEYCLOAK_KEYSET</name>
              <value>/protocol/openid-connect/certs</value>
            </env>
            <env>
              <name>MAILCHIMP_URL</name>
              <value>https://mandrillapp.com/api/1.0</value>
            </env>
            <env>
              <name>STREAMING_SASL_ENABLED</name>
              <value>true</value>
            </env>
            <env>
              <name>CORS_ENABLED</name>
              <value>true</value>
            </env>
            <env>
              <name>CORS_ALLOWED_ORIGINS</name>
              <value>*</value>
            </env>
            <env>
              <name>CORS_ALLOWED_METHODS</name>
              <value>*</value>
            </env>
            <envFrom>
              <secretRef>
                <name>kafka-access-secret</name>
              </secretRef>
            </envFrom>
          </containers>...
Honestly, it doesn't feel too bad to me. But it's also a bit overly nested for many things; I wouldn't want to read that in JSON either.

XPath (and JQ) FTW here.

(comment deleted)
Reads fine to me, although would benefit from a few element->attribute switches.
I think problem in this particular case is using YAML as DSL. Every other data format would be equally bad here. Replace YAML with TOML and you're still in same templating hell.

YAML is least worst for me, and I don't think I ever hit the problems article is showing because

* I use editor that will highlight stuff like anchors

* I often generate config from CM so it can't have those errors

* Loading into defined struct in statically typed language also makes them impossible.

I don't think YAML is great, but I still think it's the best format out there.

The only confusing problem I've run into was the sexagesimal number notation and even that was fairly obvious. Perhaps it's because I tend to overquote strings?

I mean sure, the on/off to boolean mappings are annoying, but they also become very obvious when you're parsing config because the type validation will fail. If `flush_cache` has an enum `on` but no key `True` then the type validator will instantly complain about both the missing key and the extra key in the dictionary.

Same with accidental numbers, any type check will show that the parsing failed.

I find JSON for config files to become unreadable quickly because of the non-obvious nesting and the lack of comments. You can pick a JSON extension but then you need to pick one that your tooling will support.

> I still think it's the best format out there.

What do you think of https://toml.io ?

TOML solves a lot of issues but I find it hard to visualise when you get much deeper than two or three levels.
Exactly this. I hear so many people recommend TOML over YAML.

I see the logic in it. For simple Key-value configurations, TOML is superior and more straightforward to YAML. You can add sub-level values and it isn't too bad (if there aren't too many), but beyond two levels, TOML becomes difficult to use.

If you really work in YAML in any sort of more advanced capacity (kubernetes, Ansible, CI/CD Pipelines) then you really need the complexity that YAML provides. You also get used to the "gotchas" mentioned here. Navigating them is fairly straightfoward.

I think the article was vastly overblown. Is YAML perfect? Certainly not. But you find a better way to display such complex data structures in a more human-readable and human-writable way. The complexity is YAML's strength, but it comes with caveats as all complexity generally does. I really think its the best we have.

Amazing that developers still spend so much time getting bogged down in encoding issues in 2023. Why can't we just edit some data structures directly and send send them around seamlessly? It's a deeply dysfunctional state of affairs.
For that, you'd need a set of commonly accepted data structures.

Alternatively, you can describe and send arbitrary data structures. Although that begs the question of how to process arbitrary data structures. (JSON and XML aren't arbitrary, for that matter)

There's a lot of alternatives out there. One of the most complete (in terms of specification) and very promising is concise encoding (https://concise-encoding.org/) which focuses on the duality of editable human compatible representation (as text) and efficient binary encoding/decoding. The biggest issue right now is lack of actual implementations. The project is open source (I'm not affiliated with it).
I like to write Python to manage JSON.

Keeping the data and the logic orthogonal (these effin' Fn::'s make my eyes bleed) is a win.

This is why my own configs are either ini where I know 100% that it would never become complex and take more than few lines or XML for everything else.
At CircleCI, we have had to handle many strange YAML documents. Two that come to mind:

A recursive document:

    key: &anchor
     - *anchor
The `~` character represents null:

    ~:
     - ~
This parses as a map of {null: [null]}
What were the authors trying to accomplish with these strange documents?
Break their parser, probably
The recursive anchors seemed to be user-error. Either copy+paste bugs, or an anchors places in the wrong position.

The null character would appear when people try to write a string path, and use the the `~` character without quotes.

I do think YAML is overly complex - but there is some hyperbole in this document.

- Many of these complaints are about YAML 1.1.

- YAML 1.2 was released _14 years ago_.

- The author makes some allusions to 1.2.2, and it requiring a team of people 14 years to make, but, from the yaml.com announcement they link to: “No normative changes from the 1.2.1 revision. YAML 1.2 has not been changed”

I guess my first two comments are undercut by PyYAML using YAML 1.1 (Really?! Python’s had 24 years of the Norway problem?!)

Yes, the problem is PyYAML.
The article mentions the fact that YAML 1.2 is really old and the fact that it doesn't matter because YAML 1.1 is still the most commonly supported version, and the fact that it's arguably even worse because YAML 1.2 gives different parsing results to YAML 1.1!

I highly recommend reading the article - it's very good.

This explains a lot! I just know my docker compose files were always a pain and unintuitive to write.
[flagged]
Did you create this account just to place an insulting comment? Be kind
you should be kind to idiots? then how will they learn that they are idiots?
Indeed, we're being too kind to you.
(comment deleted)