『瀚思彼岸』» 智能家居技术论坛

 找回密码
 立即注册
查看: 20076|回复: 29

[基础教程] 【HASS初级教程】3-YAML语法和JSON(上)

  [复制链接]

26

主题

553

帖子

2726

积分

金牌会员

Rank: 6Rank: 6

积分
2726
金钱
2148
HASS币
100

教程狂人

发表于 2018-9-3 23:24:23 | 显示全部楼层 |阅读模式
本帖最后由 Mirukuteii 于 2018-9-21 16:27 编辑

【HASS初级教程】3-YAML语法和JSON(上)

-------施工中------
未完成:解释性图片、简化和优化表述。

上一篇教程中,我们了解了HASS运行的基本原理,特别是核心、组件的概念,并且,已经能够从这个角度来理解配置文件的整个配置过程。
但是,若仅依靠对核心和组件的认知,以及参考官网组件文档,还是不可能彻底掌握配置文件的编写技巧。我们必须通过比较系统地学习YAML格式来准确掌握配置文件的编写规范。本篇教程将重点介绍字典、列表和缩进。

一、YAML和JSON概述

YAML.png

YAML简介

一般的标签语言通过标签对数据进行格式化,以便机器能够理解其中的含义。
YAML语言几乎不使用标签,而是利用文件内容本身的语法结构,对数据进行格式化。
YAML文件的语法结构非常严谨和重要,文档的可读性高,所以非常适合编写配置文件。

JSON简介

JSON和YAML一样,是一种实现数据序列化的方法,并且YAML和JSON可以相互转换。
YAML1.2规范中兼容了JSON,所以在HASS的YAML文件中,我们可以直接使用JSON替代标准的YAML语法。

YAML的基本规则

  • 大小写敏感
  • 禁止使用TAB,必须用空格缩进
  • 字符串可以不用引号标注
  • 英文和符号必须使用半角字符
  • #是唯一的注释方法

二、 字典结构★

1. 字典的概念

字典是一种重要的数据结构,字典(dict)这个词来源于Python等语言,YAML官方称为映射(mapping)、JSON称为对象(object)、也叫做哈希(hashes)或者散列表等。

2. 字典的特性

没有编程基础?没事,你只要按照字面意思去理解就可以!
字典就是一本工具书,里面包含很多个关键字(KEY,简称字),每个关键字对应着一段解释(Value,简称值)。

字典.jpeg

楼主认为,字典结构拥有以下特性:

1. 成对性
1个字对应1个值,字和值必然成对出现,我把这样的一对组合叫做字典的字值对(后来发现阮一峰老师把它叫做键值对)。
2. 组合性
字值对是构成字典的数据项(成员),若干个并列的字值对可以组成一本字典;只含有1个字值对的字典,本教程特称为单字典
3. 无序性
字典的字值对之间平等并列,不讲究先后顺序,字典中字值对排列的顺序不影响字典的使用和含义。
4. 唯一性
在一本字典中,字是唯一和不可重复的,不可能出现相同的字,并且字必须是一个字符串,不能是其它类型。比如,你不可能在一本字典的多个地方找到同一个字的解释。至少,在HASS中这样是不允许的。
5. 任意性
在一本字典中,值可以是任意的类型,包括复合数据类型(字典、列表)。比如,值可以是一本字典,从而构成复合字典。

3. 字典的写法

1. YAML标准写法★

name: Mirukuteii
gender: male
age: 34
···

解释:字+冒号+空格+值=字值对,N个并列的字值对构成字典。
注意:半角英文符号。YAML默认接受字符串类型,无需引号(除非使用Jinja代码,否则一般不需要为字符串类型加上引号)。

2. JSON写法

{"name":"Mirukuteii","gender":"male","age":34, ...}

解释:字+冒号+值=字值对,字值对之间通过逗号隔开,外面套上大括号,从而构成字典。
注意:半角英文符号。字必须加上引号,值的内容若为字符串也需要加上引号。冒号和逗号后面加不加空格都没关系。

为了弄明白字典这个重要概念,我们再回到上一篇教程的配置文件中进行分析:

homeassistant:                # 调用核心组件
  name: Hello                   # 配置该组件的name项,值为Hello
  latitude: 30                  # 配置该组件的latitude项,值为30
  longitude: 120                # 配置该组件的logitude项,值为120
  elevation: 0                  # 配置该组件的elevation项,值为0
  time_zone: Asia/Shanghai      # 配置该组件的time_zone项,值为Asia/Shanghai
frontend:                     # 调用前端组件

例1: 典型的字值对
单独看第2行:

name: Hello

分析:这是一个典型的字值对,它的为字符串"name",为字符串"Hello"。若找不到与其并列的字值对,我们也可以把这段代码看作为一本单字典(该字典只有1个字值对)。

例2: 典型的字典
接着,看第2-6行:

name: Hello
latitude: 30
longitude: 120
elevation: 0
time_zone: Asia/Shanghai

分析:这是一个典型的字典,它是由5个并列的字值对构成的。

例3: 典型的嵌套字典,也是一个单字典
然后,看第1-6行:

homeassistant:                # 调用核心组件
  name: Hello                   # 配置该组件的name项,值为Hello
  latitude: 30                  # 配置该组件的latitude项,值为30
  longitude: 120                # 配置该组件的logitude项,值为120
  elevation: 0                  # 配置该组件的elevation项,值为0
  time_zone: Asia/Shanghai      # 配置该组件的time_zone项,值为Asia/Shanghai

分析:这是一个典型的嵌套字典,这个字典只有1个字值对,它的homeassistant为例2中分析的那本字典。(字典作为字值对,从而构成嵌套字典);同时,该字典只有1个字值对,所以属于单字典

例4: 特殊的字典,也是一个单字典
然后,我们单独分析第7行

frontend:

分析:这是一个特殊的字典,它看上去没有值。这样不是格式错误么?答案是否定的。在HASS中,组件及其配置项并不是由配置文件构建的,而是已经存在的。实际上,frontend组件是存在配置项并且所有的配置项是有默认值的。所以,frontend组件的值一旦留空,系统就会使用默认值来配置这个组件,并不会影响到组件的加载和正常工作。实质上它是一本隐形的嵌套字典,因为它的值其实是一本隐藏的字典,这里暂不讨论,以免引起概念混淆。

例5: 典型的嵌套字典,配置文件的本质结构
最后,我们看完整的配置文件

homeassistant:                # 调用核心组件
  name: Hello                   # 配置该组件的name项,值为Hello
  latitude: 30                  # 配置该组件的latitude项,值为30
  longitude: 120                # 配置该组件的logitude项,值为120
  elevation: 0                  # 配置该组件的elevation项,值为0
  time_zone: Asia/Shanghai      # 配置该组件的time_zone项,值为Asia/Shanghai
frontend:                     # 调用前端组件

分析:这是一个典型的嵌套字典,它有2个字值对,对应的字分别为homeassistantfrontend。第1个字值对的值,又由1个字典构成,这个字典有5个字值对

例5是一个完整的配置文件,也就是说:HASS的配置文件本质上就是一本字典

本章思考题:

frontend:                     # 调用前端组件

homeassistant:                # 调用核心组件
  elevation: 0                  # 配置该组件的elevation项,值为0
  latitude: 30                  # 配置该组件的latitude项,值为30
  longitude: 120                # 配置该组件的logitude项,值为120
  time_zone: Asia/Shanghai      # 配置该组件的time_zone项,值为Asia/Shanghai
  name: Hello                   # 配置该组件的name项,值为Hello

以上代码和例5相比,有没有区别?
答案:没有区别,因为字典结构是无序的,改变字值对的顺序,并不会影响字典的意义。

二、 列表结构

1. 列表的概念

列表也是一种重要的数据结构,列表(list)这个词来源于Python等语言,YAML官方称为序列(Sequence)、JSON称为数组(Array)。

2. 列表的特性

列表比字典更易理解,就是数据的有序集合。列表也是由数据项(成员)组成的复合结构,每个数据项叫做列表的元素元素就是单纯的数据,多个元素按序存放在一个整体结构中,就成了列表。你可以把列表理解为一个大箱子,箱子里有N个按序号排列的格子,每个格子都存放了一个数据。

楼主认为,列表结构拥有以下特性:

1. 有序性
列表的元素按照先后顺序排列,元素的顺序不同,列表的含义也不同。不过,楼主认为HASS配置文件中的列表这一特性可以忽略。
2. 组合性
元素是构成列表的数据项(成员),若干个元素按照顺序排列组成一个列表;只含有1个元素的列表,本教程特称为单列表
3. 任意性
在一个列表中,元素可以是任意的类型,包括复合数据类型(字典、列表)。比如,元素可以是一本字典,从而实现嵌套的复合结构。

3. 列表的写法

1. YAML标准写法★

- apple
- banana
- orange
···

解释:短横+空格+元素内容=元素,N个顺序的元素构成列表。
注意:半角英文符号。YAML默认接受字符串类型,无需引号(除非使用Jinja代码,否则一般不需要为字符串类型加上引号)。

2. JSON写法

["apple","banana","orange", ...]

解释:元素内容=元素,元素之间通过逗号隔开,外面套上中括号,从而构成列表。
注意:半角英文符号。字符串类型的元素必须加上引号。

我们来看看下面这段例子

homeassistant:
  whitelist_external_dirs:
    - /usr/var/dumping-ground
    - /tmp

以上例子的含义是为HASS指定外部访问目录的白名单列表,也就是说这些目录将通过HASS前端暴露在网络上供人访问其中的资源。
这里只是作为编写配置文件的例子,没有特殊情况,请不要在实际使用中添加白名单,以免私密数据外泄。
下面按照YAML语法分析:
例子是一本单字典,这个单字典只有一个字值对,其值又是一本单字典。而这第二本单子典的值,则是一个列表。
即:

- /usr/var/dumping-ground
- /tmp

这个列表有2个元素,第一个元素为/usr/var/dumping-ground,第二个元素为/tmp
列表的元素是有先后顺序的,但是在HASS的实际配置中,这种先后顺序不一定是有意义的。我们可以认为HASS中,列表元素是平等并列的,交换位置,不会改变总体的含义,不过在涉及前端等的配置中,这种先后顺序可能会比较明显的表现出来,比如通过group组件显示的实体位置次序。

在HASS中,列表结构不大可能单独使用。绝大多数情况下,列表是作为字典的字值对的值而存在。其意义我们将在下一篇教程中嵌套部分重点叙述。

本章思考题:

homeassistant:
  whitelist_external_dirs:
    - /usr/var/dumping-ground
    - /tmp

以上代码如何转换为JSON格式?
答案:

{"homeassistant":{"whitelist_external_dirs":["/usr/var/dumping-ground","/tmp"]}}

三、 缩进的意义

1. 缩进的概念

缩进本没有特别的意义,只是为了提高可读性所作的一种人为的修饰方式。
但是,YAML中的缩进(借鉴于python语法)是决定数据结构的重要方法,请务必重视!

缩进就是管理行代码之间相互关系的一种语法。

2. 缩进的特性

缩进本质上不是一种数据结构,而用于构造数据结构的辅助方法。缩进的特性我归纳为以下方面。

1. 辅助性
缩进不是某种数据结构,必须依存在某种数据结构的语境中,但是不同的缩进方式将构建含义不同的数据结构。
2. 叠加性
缩进是不断叠加的,在结构完成构建之前,这种叠加效应会持续下去,所以修改上方代码的缩进会影响下方代码缩进的意思表达。
3. 可读性
使用缩进编写的YAML文件,可以很直观地看出行代码之间的层次关系。

缩进的写法:

1. YAML标准写法

name: 
  Hello

解释:(若干个空格)数据代码...,缩进就是每行内容前的空格数量。
注意:半角英文符号。

2. JSON写法
没有写法,但是缩进相当于json中{}[],等符号的具体位置。
解释:缩进就是对行代码的层次管理。
注意:半角英文符号。

缩进的意义:

1. 有效代码行

首先,我们把有意义的一行YAML代码,称为一个有效的代码行。
相对于有效的代码行而言,以下代码行是无效的:

  1. 只含有非可见字符(空格符、换行回车符等)的代码行,是无效的代码行。
  2. 由#字符作为该行首个可见字符的代码行,也是无效的代码行,因为其后所有内容都被注释了。
    这里的无效,指的是不能够被YAML所解析,并非指的是毫无作用。
    例如,下面的2行就是无效的代码行。

    
       # 我是无效的代码行

2. 意义

缩进,或者说某行代码的缩进,表示该行与其上方有效代码行之间的关系。

就上面这个例子来分析:
Hello这行代码,相对于上一个有效的代码行,即name:,缩进了2个空格。
所以,Hello这行代码,属于上一行结构的一部分。

第2个例子:

fruit: 
  - apple
  - banana
  - orange

分析:
- banana这行代码,相对于上一个有效的代码行- apple,没有缩进。
所以,- banana这行代码与- apple是并列的,同理可得- orange也是一样。
而- apple这行代码,相对于上一个有效的代码行fruits:,缩进了2个空格,
所以,- apple这行代码,是属于fruits: 这行结构的一部分。
并且,由于- banana和- orange与- apple并列,所以它们都是fruits: 这行代码的一部分。

第3个例子:

fruit: 
  - apple

vegetables:
  - tomato
  - potato

分析:
- apple,相对于上一个有效的代码行fruit: ,缩进2个空格,所以是属于fruit: 结构的一部分。
- tomato、- potato,两行代码的缩进相同,所以并列,并且相对于vegetables:,缩进了2个空格,所以属于vegetables:结构的一部分。
而- apple、- tomato、- potato,这3行代码,虽然单独看这3行的缩进相同,但是- apple和- tomato这2行代码之间,并不能建立并列的关系,因为在这两行代码之间,有缩进层次更高的vegetables:,使得- tomato、- potato已经被包含进vegetables:的结构中,不可能再和- apple产生关系。
所以,2个缩进较多、层次较低的行代码之间,如果有缩进更少、层次更高的行代码,则这2行代码必然无法再产生关联性。
最后,fruit: 、vegetables:两行代码是并列的关系。

以上的例子,用JSON表示,即:

{'fruit':['apple'], 'vegetavles':['tomato','potato']}

思考:为什么说,缩进在JSON中指的是[].{}这些符号的具体位置。













评分

参与人数 6金钱 +67 收起 理由
book123 + 10 膜拜大神!
pinkvitara + 5
ri593580645 + 2 膜拜大神!
lidicn + 20 在下对你的景仰犹如滔滔长江之水,连绵不绝.
windgo + 10 在下对你的景仰犹如滔滔长江之水,连绵不绝.
neroxps + 20 又如滚滚黄河之水,一发不可收拾…….

查看全部评分

回复

使用道具 举报

5

主题

223

帖子

2205

积分

金牌会员

Rank: 6Rank: 6

积分
2205
金钱
1982
HASS币
0
发表于 2018-9-4 01:42:49 | 显示全部楼层
我靠~膜拜大神~
回复

使用道具 举报

3

主题

206

帖子

952

积分

论坛积极会员

积分
952
金钱
746
HASS币
0
发表于 2018-9-4 11:01:36 | 显示全部楼层
雖然還看不懂,還是感謝

回复

使用道具 举报

74

主题

1942

帖子

7885

积分

元老级技术达人

积分
7885
金钱
5893
HASS币
430

活跃会员教程狂人

发表于 2018-9-4 13:06:00 | 显示全部楼层
膜拜大佬,文章写的总是这么严谨。
所有过往,皆为序章。
回复

使用道具 举报

123

主题

4626

帖子

1万

积分

管理员

囧死

Rank: 9Rank: 9Rank: 9

积分
16013
金钱
11302
HASS币
45
发表于 2018-9-4 13:06:01 | 显示全部楼层
不可多得的教程,感谢M大!
回复

使用道具 举报

7

主题

219

帖子

1298

积分

金牌会员

Rank: 6Rank: 6

积分
1298
金钱
1074
HASS币
0
发表于 2018-9-4 16:04:19 | 显示全部楼层
我来学习
回复

使用道具 举报

40

主题

3057

帖子

1万

积分

超级版主

Nero

Rank: 8Rank: 8

积分
11135
金钱
8028
HASS币
182
发表于 2018-9-4 16:09:31 | 显示全部楼层
M大加油,写好丢gitbook
Nero
回复

使用道具 举报

26

主题

553

帖子

2726

积分

金牌会员

Rank: 6Rank: 6

积分
2726
金钱
2148
HASS币
100

教程狂人

 楼主| 发表于 2018-9-4 16:30:36 | 显示全部楼层
neroxps 发表于 2018-9-4 16:09
M大加油,写好丢gitbook

等着N大帮我改教程
回复

使用道具 举报

9

主题

787

帖子

3831

积分

论坛元老

Rank: 8Rank: 8

积分
3831
金钱
3044
HASS币
87
发表于 2018-9-4 20:53:49 | 显示全部楼层
支持M大
回复

使用道具 举报

12

主题

193

帖子

1120

积分

论坛积极会员

积分
1120
金钱
927
HASS币
0
发表于 2018-9-9 12:10:51 | 显示全部楼层
这就是我日思夜想的教程,简明扼要,易懂。我这样的小白最需要了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-4-24 11:38 , Processed in 0.298402 second(s), 36 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表