Some fixes to YAML post
This commit is contained in:
parent
8166afd667
commit
b43802b396
@ -12,22 +12,21 @@ great developers and a great community. I've been hanging about the official
|
|||||||
[Discord Chat Server](https://discord.gg/c5DvZ4e), and try to give something
|
[Discord Chat Server](https://discord.gg/c5DvZ4e), and try to give something
|
||||||
back by helping people when I can.
|
back by helping people when I can.
|
||||||
|
|
||||||
One thing I noticed is that people often struggle with is the fact that the
|
One thing I noticed that people often struggle with is the YAML configuration
|
||||||
configuration is made through YAML. A strange choice for the kind of
|
files. A strange choice for the kind of quasi-programming you may want to do
|
||||||
quasi-programming you may want to do when automating your home appliances.
|
when automating your home appliances.
|
||||||
|
|
||||||
In this post I have tried to describe how YAML works, and how I think about the
|
In this post I have tried to describe how YAML works, and how I think about the
|
||||||
way it represents basic data structures. I hope it can be useful to someone...
|
way it represents basic data structures. I hope it can be useful to someone...
|
||||||
|
|
||||||
### Dictionaries and lists
|
### Dictionaries and lists
|
||||||
|
|
||||||
To understand YAML, you need to understand what it's describing. There are two
|
To understand YAML, you need to understand what it's describing. YAML works
|
||||||
main concepts: *Dictionaries* and *Lists*.
|
with two main data structures - *Dictionaries* and *Lists*.
|
||||||
|
|
||||||
|
**Lists** are easy to understand. They're just a list - ordered collections of
|
||||||
**Lists** are quite simple. It's just a list - an ordered collection of things.
|
things. There are two things you need to remember though. Let me show them to
|
||||||
There are two things you need to remember though. Let me show them to you in a
|
you in a list :)
|
||||||
list :)
|
|
||||||
|
|
||||||
- Lists are ordered. If you make a list with a dog, a cat and an elephant, the
|
- Lists are ordered. If you make a list with a dog, a cat and an elephant, the
|
||||||
dog will be first, the elephant will be last and the cat will be in between.
|
dog will be first, the elephant will be last and the cat will be in between.
|
||||||
@ -42,17 +41,20 @@ your home.
|
|||||||
- A list of things to pack for the vacation next week
|
- A list of things to pack for the vacation next week
|
||||||
- The list of passwords on a post-it under your keyboard
|
- The list of passwords on a post-it under your keyboard
|
||||||
|
|
||||||
**Dictionaries** are not much more complicated. You've probably seen it in some
|
**Dictionaries** (or *dicts* for short) are not much more complicated. You've
|
||||||
way or another, but perhaps with a different name. In different programming
|
probably encountered them in some way or another, but perhaps with a different
|
||||||
languages they can be called *dictionaries*, *hashes*, *maps*, *hash tables*,
|
name. In different programming languages they can be called *dictionaries*,
|
||||||
*tables*, *collections* or even just *objects*. The technical name is
|
*hashes*, *maps*, *hash tables*, *tables*, *collections* or even just
|
||||||
*Associative Array*.
|
*objects*. The technical name is *Associative Array*.
|
||||||
|
|
||||||
Regardless of name, the concept is simple. A dictionary is a collection of
|
Regardless of name, the concept is simple. A dictionary is an unordered
|
||||||
key-value pairs. That is, a Name for something, and that Something. The name -
|
collection of entries - where each entry has a *Key* and a *Value*.
|
||||||
the *key* must be unique. The same key can not be used twice in the same
|
The Key can be thought of as a name or title for the entry, and the Value is
|
||||||
dictionary. The Something - the *value* can be anything at all, just like the
|
the data of the entry. Remember:
|
||||||
items in a list.
|
|
||||||
|
- Keys are unique. Two entries in the same dict can not have the same key.
|
||||||
|
- Values can be anything, just like the items in a list - Strings, integers,
|
||||||
|
booleans, dictionaries or lists.
|
||||||
|
|
||||||
Let's look at some sample dictionaries:
|
Let's look at some sample dictionaries:
|
||||||
|
|
||||||
@ -64,9 +66,9 @@ Thursday: Pea soup and pancakes
|
|||||||
Friday: Pizza
|
Friday: Pizza
|
||||||
```
|
```
|
||||||
|
|
||||||
Each day is labeled by a key, and has a value - what are you going to eat that day.
|
Each day is labeled by a key, and has a value - what are you going to eat that
|
||||||
Note that while you could add another `Wednesday` to the end of the list, it
|
day. Note that while you could add another `Wednesday` to the end of the list,
|
||||||
wouldn't really make sense. Thus keys have to be unique. The values doesn't
|
it wouldn't really make sense. Thus keys have to be unique. The values doesn't
|
||||||
however. It would make perfect sense to eat pizza again on Saturday.
|
however. It would make perfect sense to eat pizza again on Saturday.
|
||||||
|
|
||||||
Since keys are unique, their order is not important:
|
Since keys are unique, their order is not important:
|
||||||
@ -89,13 +91,13 @@ Name: Thomas Lovén
|
|||||||
Email: thomasloven@example.com
|
Email: thomasloven@example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
That's a dictionary. Looks kind of like a database of a sort, doesn't it?
|
That's a dictionary. Looks kind of like a database of a sort, doesn't it? Like
|
||||||
Like the address book in your email program? Ah! But don't get fooled. The
|
the address book in your email program? Ah! But don't get fooled. The address
|
||||||
address book is a **list**, not a **dictionary**. However - the *items* in the
|
book is a **list**, not a **dictionary**. However - the *items* in the list are
|
||||||
list are *dictionaries*.
|
*dictionaries*.
|
||||||
|
|
||||||
|
|
||||||
Let's add on to that dictionary:
|
Let's add on to that dict:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
Name: Thomas Lovén
|
Name: Thomas Lovén
|
||||||
@ -103,9 +105,9 @@ Email: thomasloven@example.com
|
|||||||
Hobbies: singing, woodworking, home automation
|
Hobbies: singing, woodworking, home automation
|
||||||
```
|
```
|
||||||
|
|
||||||
Now we added an entry to the dictionary where the value is a list. I have three
|
Now we added an entry to the dict where the value is a list. I have three
|
||||||
hobbies. This illustrates that the value of a dictionary key-value pair can be
|
hobbies. This illustrates that the value of a dictionary entry can be anything.
|
||||||
anything. Even a dictionary:
|
Even a dictionary:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
Name: Thomas Lovén
|
Name: Thomas Lovén
|
||||||
@ -124,8 +126,8 @@ Phones: Home: +46 (0)XX XXXXXX, Work: +40 (0)XX XXXXXX
|
|||||||
Children: Name: N, Age: 3 ; Name: H, Age: 1
|
Children: Name: N, Age: 3 ; Name: H, Age: 1
|
||||||
```
|
```
|
||||||
|
|
||||||
But that this point things are getting advanced. It's hard to keep track of
|
But at this point things are getting advanced. It's hard to keep track of what
|
||||||
what is a dictionary and what is a list and what contains what...
|
is a dict and what is a list and what contains what...
|
||||||
|
|
||||||
If only there was a language to describe these concepts... a sort of Markup
|
If only there was a language to describe these concepts... a sort of Markup
|
||||||
Language, if you will... but who needs Yet Another one of those?
|
Language, if you will... but who needs Yet Another one of those?
|
||||||
@ -135,23 +137,23 @@ Let me tell you about
|
|||||||
### JSON
|
### JSON
|
||||||
|
|
||||||
Javascript Structured Object Notation - [JSON](https://www.json.org/). You
|
Javascript Structured Object Notation - [JSON](https://www.json.org/). You
|
||||||
thought I was going to say YAML, didn't you? We'll get there too.
|
thought I was going to say YAML, didn't you? Soon...
|
||||||
|
|
||||||
JSON is a simple way of writing down the concepts described above which can be
|
JSON is a simple way of writing down the concepts described above, which can be
|
||||||
easily understood both by humans and by computers.
|
easily understood both by humans and by computers.
|
||||||
|
|
||||||
Basically, there are *objects* and *arrays*, but let's call them
|
JSON describes *object* and *arrays*, there are *objects* and *arrays*, but
|
||||||
*dictionaries* and *lists* instead.
|
let's call them *dictionaries* and *lists* instead.
|
||||||
|
|
||||||
*lists* are surrounded by square brackets and contain items separated by commas.
|
*lists* are surrounded by square brackets and contain items separated by commas.
|
||||||
The items can be strings, numbers, dictionaries, lists or any of the magic
|
The items can be strings, numbers, dictionaries, lists or any of the magic
|
||||||
values `true`, `false`, or `null`.
|
values `true`, `false`, or `null`.
|
||||||
|
|
||||||
*Dictionaries* are surrounded by curly braces and contain key-value pairs
|
*Dictionaries* are surrounded by curly braces and contain entries separated by
|
||||||
separated by commas. Each key-value pair has the key, a colon and the value.
|
commas. The key and value of each entry is separated by a colon. Keys must be
|
||||||
Keys must be strings, but values can be anything that can be in a list.
|
strings, but values can be anything that can be in a list.
|
||||||
|
|
||||||
Let's look at our dictionary from above in JSON format:
|
Let's look at our dict from above in JSON format:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@ -174,12 +176,12 @@ Let's look at our dictionary from above in JSON format:
|
|||||||
```
|
```
|
||||||
|
|
||||||
I added some line breaks and indentations to make it more pretty, but this is
|
I added some line breaks and indentations to make it more pretty, but this is
|
||||||
much easier to read. Even the last key-value pair about my children.
|
much easier to read. Even the last entry with the nested dict-list-dict about
|
||||||
Two things to note
|
my children. Two things to note:
|
||||||
|
|
||||||
- You don't need quotes around the keys, but you do around values that are
|
- You don't need quotes around the keys, but you do around string values. If
|
||||||
strings. If you want whitespace in a key (which is entirely OK) it must be
|
you want whitespace in a key (which is entirely OK) it must be quoted,
|
||||||
quoted, though.
|
though.
|
||||||
- The indentations and newlines I added, and in fact any whitespace not in
|
- The indentations and newlines I added, and in fact any whitespace not in
|
||||||
quotes, is ignored.
|
quotes, is ignored.
|
||||||
|
|
||||||
@ -190,11 +192,11 @@ OK. Now you understand one markup language. Let's learn something different.
|
|||||||
[YAML](http://yaml.org/) Ain't a Markup Language - but it's pretty darn close,
|
[YAML](http://yaml.org/) Ain't a Markup Language - but it's pretty darn close,
|
||||||
to be honest.
|
to be honest.
|
||||||
|
|
||||||
While probably not historically accurate, YAML can be seen as an evolution of
|
While probably not historically accurate, YAML can be seen as an evolution or
|
||||||
JSON. In fact, any valid JSON is also valid YAML. That might be important to
|
superset of JSON. In fact, any valid JSON is also valid YAML. That might be
|
||||||
remember. There are some notable differences, though.
|
useful to remember. There are some notable differences, though.
|
||||||
|
|
||||||
First of all, YAML does away with the braces. Instead items in lists are
|
First of all, YAML doesn't require braces. Instead items in lists are
|
||||||
separated by newlines where each item starts with a dash:
|
separated by newlines where each item starts with a dash:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@ -217,13 +219,19 @@ Some things to note:
|
|||||||
blessing and a curse. For example `"true"` is a string, but `true` is a
|
blessing and a curse. For example `"true"` is a string, but `true` is a
|
||||||
boolean value.
|
boolean value.
|
||||||
- Indentation is important. Item 3 in the list stretches over multiple lines.
|
- Indentation is important. Item 3 in the list stretches over multiple lines.
|
||||||
Each line after the first one is indented (with an equal number of spaces,
|
Each line after the first one is indented (with an equal number of spaces -
|
||||||
*NOT* tabs). The same is true for Item 5, which is a list. Each item in the
|
*NOT* tabs). The same is true for Item 5, which is a list. Each item in the
|
||||||
sub-list is indented with an equal number of spaced.
|
sub-list is indented with an equal number of spaced.
|
||||||
- The items of the list are not of the same type. Most are strings, but item 5
|
- The items of the list are not of the same type. Most are strings, but item 5
|
||||||
is a list.
|
is a list.
|
||||||
|
|
||||||
Dictionaries are also separated on lines with the key, a colon and the value:
|
I'll just take the opportunity to say this again: Indentation is important.
|
||||||
|
Probably the most important concept of YAML.
|
||||||
|
|
||||||
|
Slightly simplified one can say that by indenting line, those line become a
|
||||||
|
continuation of the line above, until the next de-dented line.
|
||||||
|
|
||||||
|
Dictionaries are also written one entry per line, as `key: value`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
Name: Thomas Lovén
|
Name: Thomas Lovén
|
||||||
@ -245,12 +253,11 @@ Children:
|
|||||||
|
|
||||||
Things to note:
|
Things to note:
|
||||||
|
|
||||||
- The value corresponding to the key `Hobbies` is a list. Like above, each line
|
- The value of `Hobbies` is a list. Like above, each line of the value is
|
||||||
of the value is indented by an equal number of spaces.
|
indented by an equal number of spaces.
|
||||||
- The value corresponding to the key `Phones` is a dictionary. The same
|
- The value of `Phones` is a dictionary. The same indentation rules apply.
|
||||||
indentation rules apply.
|
- The value of `Children` is a list where each item is a dictionary. So each
|
||||||
- The value corresponding to the key "Children" is a list where each item is a
|
line in each dictionary is indented twice.
|
||||||
dictionary. So each line in each dictionary is indented twice.
|
|
||||||
- The second entry in the list of children uses a contracted form, where the
|
- The second entry in the list of children uses a contracted form, where the
|
||||||
first key-value pair of the dictionary is put on the same line that signifies
|
first key-value pair of the dictionary is put on the same line that signifies
|
||||||
the list item. More on this later.
|
the list item. More on this later.
|
||||||
@ -265,19 +272,20 @@ any other. Indentation errors.
|
|||||||
|
|
||||||
*Indentation is important*
|
*Indentation is important*
|
||||||
|
|
||||||
It *must* be correct, or the YAML won't be accepted by the parser, or it will
|
It *must* be correct or the YAML either won't be accepted by the parser or will
|
||||||
describe something entirely different from what you intended.
|
describe something entirely different from what you intended.
|
||||||
|
|
||||||
The only advice I can give is to think carefully about the structure of the
|
The only advice I can give is to think carefully about the structure of the
|
||||||
data you are trying to represent. What is your object? Is it a dictionary or a
|
data you are trying to represent. What is your object? Is it a dictionary or a
|
||||||
list? Where is it contained? Is it freestanding? Is it the value of a
|
list? Where is it contained? Is it freestanding? Is it an entry in a dict? Is
|
||||||
dictionary key-value pair? Is it an item in a list? What is it's parent? What
|
it an item in a list? What is it's parent? What are it's children? What are
|
||||||
are it's children? What are it's siblings?
|
it's siblings?
|
||||||
|
|
||||||
It it's a complex structure, it might help to make a drawing on actual paper.
|
If you have a complex structure - say some nested cards in lovelace - it might
|
||||||
|
help to make a drawing on actual paper of what you want.
|
||||||
|
|
||||||
In the YAML dictionary sample above, I used a contracted for in my list of
|
In the YAML dictionary sample above, I used a contracted form in my list of
|
||||||
dictionaries. This is common practice, but may be a bit confusing at first
|
dicts. This is common practice, but may be a bit confusing at first
|
||||||
since it makes the indentation unclear.
|
since it makes the indentation unclear.
|
||||||
|
|
||||||
If might be easier to understand the structure of the document if you use the
|
If might be easier to understand the structure of the document if you use the
|
||||||
@ -293,15 +301,32 @@ Children:
|
|||||||
Age: 1
|
Age: 1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Also, remember that dictionary entries are unordered. The YAML below describes
|
||||||
|
the same thing as that above, but might be more confusing.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Children:
|
||||||
|
- Name: N
|
||||||
|
Age: 3
|
||||||
|
- Age: 1
|
||||||
|
Name: H
|
||||||
|
```
|
||||||
|
|
||||||
|
Often software generated YAML (such as what's produced by
|
||||||
|
[lovelace-gen](https://github.com/thomasloven/homeassistant-lovelace-gen))
|
||||||
|
write the entries out in such a way that the keys are ordered alphabetically.
|
||||||
|
|
||||||
### Advanced topics
|
### Advanced topics
|
||||||
|
|
||||||
#### Comments
|
#### Comments
|
||||||
|
|
||||||
Adding comments to your code makes it easier to understand. Both to other
|
Adding comments to your code makes it easier to understand. Both to other
|
||||||
people, and - more importantly - to you when you return to it in six months
|
people, and - more importantly - to your self when you return to it in six
|
||||||
because something stopped working.
|
months because something stopped working.
|
||||||
|
|
||||||
In YAML, comments begin with a number sign `#`, last until the end of the line
|
In YAML, comments begin with a number sign `#`, last until the end of the line
|
||||||
and are ignored by the parser.
|
and are simply ignored by the parser.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# A dictionary about me
|
# A dictionary about me
|
||||||
Name: Thomas Lovén
|
Name: Thomas Lovén
|
||||||
@ -312,6 +337,8 @@ Hobbies:
|
|||||||
- woodworking
|
- woodworking
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want a number sign in your entry, the entry must be quoted.
|
||||||
|
|
||||||
#### Spaces and colons
|
#### Spaces and colons
|
||||||
|
|
||||||
As mentioned, YAML doesn't require quotes around strings, but they are allowed.
|
As mentioned, YAML doesn't require quotes around strings, but they are allowed.
|
||||||
@ -323,8 +350,9 @@ Quotes can be useful to tweak the parsing. Imagine for example the following lis
|
|||||||
- Halflife 2: Episode Two
|
- Halflife 2: Episode Two
|
||||||
```
|
```
|
||||||
|
|
||||||
This is a list of strings, right? Wrong. The third entry is a dictionary with
|
This is a list of strings, right? Wrong. The third entry is a dictionary with a
|
||||||
the key "Halflife 2" and the value "Episode Two" (keys can contain spaces, by the way).
|
single entry "Halflife 2" with value "Episode Two" (keys can contain spaces, by
|
||||||
|
the way).
|
||||||
|
|
||||||
To fix this, you can use quotes:
|
To fix this, you can use quotes:
|
||||||
```yaml
|
```yaml
|
||||||
@ -357,9 +385,17 @@ and make the data hard to read instead. In the end it's a matter of taste.
|
|||||||
Note that there are still no quotes. That's OK as long as you don't want
|
Note that there are still no quotes. That's OK as long as you don't want
|
||||||
commas, } or ] in the value.
|
commas, } or ] in the value.
|
||||||
|
|
||||||
|
Further, YAML allows single line comma separated lists without braces.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Hobbies: singing, woodworking, home automation
|
||||||
|
```
|
||||||
|
|
||||||
|
This also means that a string containing a comma must be quoted.
|
||||||
|
|
||||||
#### Merging
|
#### Merging
|
||||||
|
|
||||||
Dictionaries can be merged using the key: `<<`. For example:
|
Dictionaries can be merged using the merging operator: `<<`. For example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
a key: a value
|
a key: a value
|
||||||
@ -384,8 +420,8 @@ b key: b value
|
|||||||
d key: d value
|
d key: d value
|
||||||
```
|
```
|
||||||
|
|
||||||
In short, the `<<` key takes a dictionary as its value, and merges it into the
|
In short, the `<<` operator takes a dictionary as its value, and merges it into
|
||||||
parent dictionary.
|
the parent dictionary.
|
||||||
|
|
||||||
|
|
||||||
#### Node anchors
|
#### Node anchors
|
||||||
@ -401,8 +437,8 @@ my_dict: &my_dict
|
|||||||
c: 3
|
c: 3
|
||||||
```
|
```
|
||||||
|
|
||||||
In this case `&my_dict` is NOT the value corresponding to the key `my_dict`,
|
In this case `&my_dict` is NOT the value of `my_dict`, but a node
|
||||||
but a node anchor - as signified by the ampersand `&`.
|
anchor - as signified by the ampersand `&`.
|
||||||
|
|
||||||
The anchor saves the value for later reuse and can be recalled any number of
|
The anchor saves the value for later reuse and can be recalled any number of
|
||||||
times using an asterisk `*`:
|
times using an asterisk `*`:
|
||||||
@ -456,13 +492,14 @@ extended version:
|
|||||||
c: 3
|
c: 3
|
||||||
```
|
```
|
||||||
|
|
||||||
At this point, understanding how this will parse shouldn't be a problem to you.
|
You should be able to guess how this parses out.
|
||||||
|
|
||||||
Now, for my final trick:
|
Now, for my final trick:
|
||||||
|
|
||||||
#### Merging while defining.
|
#### Merging while defining.
|
||||||
|
|
||||||
The problem with the above examples is that you need to put the definition
|
The problem with the above examples is that you need to put the definition
|
||||||
somewhere. The YAML snippets above will have the dictionary keys `a
|
somewhere. The YAML snippets above will have the dictionary entries `a
|
||||||
dictionary`and `base` defined and set no matter what. Sometimes that's
|
dictionary`and `base` defined and set no matter what. Sometimes that's
|
||||||
impractical, which is why you often see the following in homeassistant
|
impractical, which is why you often see the following in homeassistant
|
||||||
packages:
|
packages:
|
||||||
@ -483,7 +520,7 @@ homeassistant:
|
|||||||
icon: mdi:home
|
icon: mdi:home
|
||||||
```
|
```
|
||||||
|
|
||||||
The `package.node_anchors` key in the `customize` dictionary contains a
|
The `package.node_anchors` entry in the `customize` dictionary contains a
|
||||||
dictionary of stuff that is simply ignored. Anything you put there will have no
|
dictionary of stuff that is simply ignored. Anything you put there will have no
|
||||||
effect on the package, so it's a great place to define anchors.
|
effect on the package, so it's a great place to define anchors.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user