适合人群:入门级

JSON 和 JSON 转义

21 世纪初,Douglas Crockford 寻找一种简便的数据交换格式,能够在服务器之间交换数据。当时通用的数据交换语言是 XML,但是 Douglas Crockford 觉得 XML 的生成和解析都太麻烦,所以他提出了一种简化格式,也就是 JSON。

{"云原生":"Kubernetes"}json.Marshal

你可能会有这样的疑问:既然 JSON 字符串结构简单,为什么不直接使用字符串拼接的方式,而是要使用 JSON 序列化接口呢?

"{"云原生":"\"Kubernetes\""}

JSON 转义

(")(\)\"""\x22"\042

在 Python 中,下面的代码将会产生语法错误

1

print "Cloud Navite "Hello World!".";

而另一段 Python 代码则会产生符合预期的结果

1

print "Cloud Navite \"Hello World!\".";
{"云原生":""Kubernetes""}{"云原生":"\"Kubernetes\""}

JSON 转义机制如下图:

\“\\、\"、\/、\b、\f、\n、\r、\t\uD83D\uDE02

JSON 语法

在讲具体案例之前,复习一下 JSON 语法,忘记的可以翻阅该章节。

JSON 语法简单来说就是四条:

  • 数据在名称/值对中

  • 数据由逗号分隔

  • 花括号保存对象

  • 方括号保存数组

声明:以下使用的对象均来自于以下内容

{

    "virtualeNB":[

        {"virteNBName":"virt1","virteNBNum":5, "begineNBID":0,"beginCtlPort":6000, "beginDataPort":7000,"virtIPNum":5},

       {"virteNBName":"virt2", "virteNBNum":10,"begineNBID":10, "beginCtlPort":6000,"beginDataPort":7000, "virtIPNum":10}

    ],

    "eRAN":[

        {"eRANName":"eNB1","eRANID":3002, "ctlPort":36412, "dataPort":2152},

        {"eRANName":"eNB2","eRANID":10000, "ctlPort":36412, "dataPort":2152}

    ]

}

1. JSON 名称/值对

JSON 数据的书写格式是:名称:值,这样的一对。即名称在前,该名称的值在冒号后面。例如:

1

"virteNBName":"virt1"

"virteNBName""virt1"

名称和值得类型可以有以下几种:

  • 数字(整数或浮点数)

  • 字符串(在双引号中)

  • 逻辑值(true 或 false)

  • 数组(在方括号中)

  • 对象(在花括号中)

  • null

2. JSON 数据由逗号分隔

譬如:

"virteNBName":"virt1", "virteNBNum":5, "begineNBID":0
,

[

   {"eRANName":"eNB1", "eRANID":3002,"ctlPort":36412, "dataPort":2152},

   {"eRANName":"eNB2", "eRANID":10000,"ctlPort":36412, "dataPort":2152},

]

上面这个就是错误的,因为在数组中,两个对象之间需要逗号,但是到这个数组末尾了,不需要加逗号了。

3. JSON 花括号保存对象

对象可以包含多个名称/值对,如:

1

{"eRANName":"eNB1", "eRANID":3002, "ctlPort":36412, "dataPort":2152}

这一点也容易理解,与这条 JavaScript 语句等价:

1
2
3
4

"eRANName" = "eNB1"
"eRANID" = 3002
"ctlPort" = 36412
"dataPort" = 2152

4. JSON 方括号保存数组

数组可包含多个对象:

"eRAN":[
    {"eRANName":"eNB1", "eRANID":3002, "ctlPort":36412, "dataPort":2152},
    {"eRANName":"eNB2", "eRANID":10000, "ctlPort":36412, "dataPort":2152}
]

在上面的例子中,对象 “eRAN” 是包含 2 个对象的数组。每个对象代表一条基站的记录。

上面四条规则,就是 JSON 格式的所有内容。

案例

一个由特殊字符导致 JSON 格式的 Apache APISIX 访问日志/日志系统的 BUG

access_logngx_http_log_module
access.log
1
2
3
4

log_format  main  '$remote_addr [$time_local] "$request" '
'$status $bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main buffer=32k;

logs/access.loglog_formatbuffer=32k
access_logApache APISIX
(Elasticsearch+Filebeat+Kibana)

通常,为了方便分析,会将 Apache APISIX 访问日志输出为 JSON 字符串,其配置如下:

log_format main '{"remote_addr":"$remote_addr","time_local":"$time_local","request":"$request",'

  '"status":"$status","bytes_sent":"$bytes_sent","http_referer":"$http_referer",'

'"http_user_agent":"$http_user_agent","http_x_forwarded_for":"$http_x_forwarded_for"}';

access_log  logs/access.log  main buffer=32k;

"
log_formatescape=json
1
2
3
4

Syntax:	log_format name [escape=default|json|none] string ...;
Default:
log_format combined "...";
Context: http

escape=json
"//"//“\n”, “\r”, “\t”, “\b”, “\f”, or “\u00XX”
log_format

log_format main escape=json '{"remote_addr":"$remote_addr","time_local":"$time_local","request":"$request",'

 '"status":"$status","bytes_sent":"$bytes_sent","http_referer":"$http_referer",'

'"http_user_agent":"$http_user_agent","http_x_forwarded_for":"$http_x_forwarded_for"}';

"

JSON 与其他格式的比较

JSON vs XML

JSON 与 XML 最大的不同在于 XML 是一个完整的标记语言,而 JSON 不是。这使得 XML 在程序判读上需要比较多的功夫。主要的原因在于 XML 的设计理念与 JSON 不同。XML 利用标记语言的特性提供了绝佳的延展性(如 XPath),在数据存储,扩展及高级检索方面具备对 JSON 的优势,而 JSON 则由于比 XML 更加小巧,以及浏览器的内建快速解析支持,使得其更适用于网络数据传输领域。

!"#$%&'()*+,/;<=>?@[\]^{|}~-.

JSON vs YAML

JSON 格式简单易上手,但没有了 YAML 的一目了然,尤其是 JSON 数据很长的时候,会让人陷入繁琐复杂的数据节点查找中。通常我会使用在线 JSON 格式化工具,来更方便的对 JSON 数据进行节点查找和解析。

个人认为,YAML 几乎将 JSON 秒成渣渣,这里直接引用 YAML 官方文档 关于 YAML 的总结:

  • YAML 的可读性好

  • YAML 和脚本语言的交互性好

  • YAML 使用实现语言的数据类型

  • YAML 有一个一致的信息模型

  • YAML 易于实现

  • YAML 可以基于流来处理

  • YAML 表达能力强,扩展性好

  • YAML 可以写注释

There Is One More Thing

从结构上看,不仅仅是 JSON、YAML、XML,大部分或者所有的数据(data)最终都可以分解成三种类型:

"云原生"
["Kubernetes", "Istio"]
"CloudNative": "Kubernetes"

参考

  • JSON 官网:https://www.json.org/json-en.html
  • JSON 维基百科:https://en.wikipedia.org/wiki/JSON
  • 数据类型和 Json 格式–阮一峰:https://www.ruanyifeng.com/blog/2009/05/data_types_and_json.html
  • YAML Ain’t Markup Language (YAML™) Version 1.1:https://yaml.org/spec/1.1/index.html
  • World Wide Web Consortium:https://www.w3.org/TR/xml11/
  • 自己最初了解 JSON 时总结的一篇文章: https://blog.csdn.net/qq_15437667/article/details/50957996
转文至此。