PythonのPyYAMLでJSON形式の文字列が読み込めたのが不思議で調べてみた

## 概要

勘違いからjson形式の文字列を、```yaml.load``` で読み込んでしまったのですが、エラーがでず、読み込めてしまったので、不思議に思って調べてみました。


## 先に結論

YAML1.2からJSONを公式サブセットとする変更が入っているそうです(知らなかった

YAML Ain’t Markup Language (YAML™) Version 1.2
http://yaml.org/spec/1.2/spec.html

>This document reflects the third version of YAML data serialization language.

>この改訂の主な目的は、YAMLをJSONを公式サブセットとして遵守することです。(Google翻訳)


## 検証

以下のように、何を思ったのかJSON形式の文字列をYAMLライブラリで読み込んでしまいました。

```sh
> pip install pyyaml
```

```python:test.py
import yaml
import pprint

if __name__ == '__main__':
  jsonStr = '''
{
  "hoge": {
    "list": [
      {
        "name": "hoge",
        "value": "foo"
      },
      {
        "name": "huge",
        "value": "foo!"
      }
    ]
  }
}
  '''

  pprint.pprint(yaml.load(jsonStr))
```

```sh
> python test.py

{'hoge': {'list': [{'name': 'hoge', 'value': 'foo'},
                   {'name': 'huge', 'value': 'foo!'}]}}
```

読み込めてしまったので、あれ？YAMLとJSONって互換性あったっけ？と思い、じゃあ```json``` ライブラリでYAML形式の文字列読み込めるの？をやってみました。

```python:test.py
import json
import pprint

if __name__ == '__main__':
  yamlStr = '''
hoge:
  list:
  - name: hoge
    value: foo
  - name: huge
    value: foo!
  '''

  pprint.pprint(json.loads(yamlStr))
```

```sh
> python test.py

json.loads(yamlStr)
Traceback (most recent call last):
  File "test.py", line 14, in <module>
    pprint.pprint(json.loads(yamlStr))
  File "/Users/hoge/.anyenv/envs/pyenv/versions/3.6.6/lib/python3.6/json/__init__.py", line 354, in loads
    return _default_decoder.decode(s)
  File "/Users/hoge/.anyenv/envs/pyenv/versions/3.6.6/lib/python3.6/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/Users/hoge/.anyenv/envs/pyenv/versions/3.6.6/lib/python3.6/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)

```

だめでした。
PyYAMLが対応しているだけかなと、他のruamel.yamlってライブラリで試してみました。

```sh
> pip install ruamel.yaml
```

```python:test.py
from ruamel.yaml import YAML
import pprint

if __name__ == '__main__':
　　jsonStr = '''
{
  "hoge": {
    "list": [
      {
        "name": "hoge",
        "value": "foo"
      },
      {
        "name": "huge",
        "value": "foo!"
      }
    ]
  }
}
  '''

　　yaml=YAML(typ='safe')
　　pprint.pprint(yaml.load(jsonStr))
```

```sh
> python test.py

{'hoge': {'list': [{'name': 'hoge', 'value': 'foo'},
                   {'name': 'huge', 'value': 'foo!'}]}}
```

こちらでも読み込めました。
じゃあ、大抵のYAMLライブラリはJSON形式を読み込める？

と思ってRubyで試してみました。

```ruby:test.rb
require 'yaml'
require 'pp'

jsonStr = <<-"EOS"
{
  "hoge": {
    "list": [
      {
        "name": "hoge",
        "value": "foo"
      },
      {
        "name": "huge",
        "value": "foo!"
      }
    ]
  }
}
EOS

pp(YAML.load(jsonStr))
```

```sh
> ruby test.rb
{"hoge"=>
  {"list"=>
    [{"name"=>"hoge", "value"=>"foo"}, {"name"=>"huge", "value"=>"foo!"}]}}
```

ほう！読み込めるんですね。

YAMLライブラリでJSONは読み込める。
JSONライブラリでYAMLは読み込めない。

なにか見えてきたので、ググってみました。

json --- JSON エンコーダおよびデコーダ
https://docs.python.org/ja/3/library/json.html

>注釈 JSON は YAML 1.2 のサブセットです。


YAML Ain’t Markup Language (YAML™) Version 1.2
http://yaml.org/spec/1.2/spec.html

>This document reflects the third version of YAML data serialization language.

>この改訂の主な目的は、YAMLをJSONを公式サブセットとして遵守することです。
(Google翻訳)


正直、知らなかったです。

ウィキペディアを見てみると英語版の方だと、記載がありました。

https://en.wikipedia.org/wiki/YAML
>making YAML 1.2 a superset of JSON.

日本語版だと類似という記述だけでした。

https://ja.wikipedia.org/wiki/YAML

>類似の規格としてJSONがある。

## 教訓

普段良く使うフォーマットの仕様はしっかり把握しておきましょう。


## 参考

YAML Ain’t Markup Language (YAML™) Version 1.2
http://yaml.org/spec/1.2/spec.html

YAML
https://en.wikipedia.org/wiki/YAML