備忘録：epubcheckのために吐き出されるjsonを見てみた（追記）

#epubcheckを読んでいく
モジュール：epubcheckを読み解き、exe化した時もエラーを吐かないようにするのが目標です。道半ば。

##前回までのあらすじ
epubのチェック用にpythonで自動化を目論んだらモジュール：epubcheckがexe化した時に動かないので、初心者としては延々と格闘する羽目になっている。（exe化しないとpython使えない他の人が使う時に面倒なのでexe化したい……のだが、もはやここまで来るとexe化のための手間の方が遥かに大きくなっているけど退けない）
https://qiita.com/blue_red_violet/items/4647cd41ba7c2fc9eef7

##今回やること
読む。ひたすらコードを読む。

##前回省いた内容
「おいおいエラーの根源まで遡らず、なぜ途中でprintさせたんだい？」という疑問を多分誰あろう未来の自分が抱くだろう。

json\decoder.py line 337 & line355

上記のエラーは、そもそもエラーを吐き出すためのものだと思ったからだ。（違ってたら死ぬ。よく読もう）

```
    def decode(self, s, _w=WHITESPACE.match):
        obj, end = self.raw_decode(s, idx=_w(s, 0).end())
        end = _w(s, end).end()
        if end != len(s):
            raise JSONDecodeError("Extra data", s, end)
        return obj

    def raw_decode(self, s, idx=0):
        """Decode a JSON document from ``s`` (a ``str`` beginning with
        a JSON document) and return a 2-tuple of the Python
        representation and the index in ``s`` where the document ended.

        This can be used to decode a JSON document from a string that may
        have extraneous data at the end.

        """
        try:
            obj, end = self.scan_once(s, idx)
        except StopIteration as err:
            raise JSONDecodeError("Expecting value", s, err.value) from None
        return obj, end
```

この中の、

```
raise JSONDecodeError("Extra data", s, end)
```

と

```
raise JSONDecodeError("Expecting value", s, err.value) from None
```

が該当箇所。
実際最後に表示されるエラーは

```
json.decoder.JSONDecodeError:Expecting value: line 1 column 1 (char 0)
```

なので、合っているはずだ。と、思う。

でもなんでraise JSONDecodeErrorで２つ引っかかっているんだろう？
と、思ったので、もっとちゃんとコード読もうと思いました。

##途中のコメント、何て？
「s（JSONドキュメントで始まるstr）からjsonドキュメントをデコードし、ドキュメントが終了した場所のsの中に、python方式で書いてindex添えて返しておくよ」

「この関数使うと末尾に余分なデータのあるっぽいjsonをデコードした時、JSONDecodeError発生させられるよ」

そうか、だから末尾の余分なデータを取るために.stripを使え※と忠告されたのか……。

※epubcheck/checker.py line 58の記述のこと

```
self.result_data = json.loads(self._stdout.decode().strip())
```

としてみたのだが、エラー内容にも変化がなく、効果がなかった。

しかしコメントをちゃんと読んだ結果（最初からよく読もう）、確かに適切な処置だとも理解出来た。
では何故エラーが消えないのだろう？
.strip()をつける場所が違うのか？

##理解できていないこと
・Errorを吐かせるための行をエラー原因だと言われたのに、それ以後のエラー箇所にエラー原因を求めているが、違うのでは？

pythonがエラーだというのならエラーなのだろう。

```
raise JSONDecodeError("Expecting value", s, err.value) from None
```

だが、このうちのどこにエラー原因が存在するのだろうか？

from None？　err.value？　s？
そもそも君たち三人ともどこで何している人？

##というわけでちゃんとコードを読みたい
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
で検索した時に出てきた以下の質問が参考になる、んじゃないかな～と思っていた時代がある。
https://teratail.com/questions/140167

自分の場合、どこにあたるのかがさっぱり分からなくて参考にするのを諦めていた。
だが、ちゃんとコードを読もうと思った今、役に立つのでは？
あるいは、役に立たないと分かることで、原因の特定が進むのでは？

我々取材班は期待とともにコードのジャングルに潜っていった。

###
公式ドキュメントを読むとfrom Noneは無罪だと分かった。
https://docs.python.org/ja/3/library/exceptions.html

```
raise new_exc from None または original_exc
```

とならねばいけないと書いてある。

ではerr.valueは？
errはexcept StopIteration as errとしているので分かる。
err.valueは、つまりerrの値を取得しているんだろう。
Errorをraiseして表示するのに必要だし分かる。

sはコメント内にあった通り、s（JSONドキュメントで始まるstr）なのだろう。
これが怪しい。JSONドキュメントで始まる文字列のはずなのに、JSONがおかしかったらエラーが出るよね。

###じゃあjsonは？
上記の通り、吐き出されたjsonに問題があるのではないかと考え、またしても先達の助力を得てツール利用の紹介に従い、下記を使用してみた。
https://jsonlint.com/

出る。
エラーが出る。

以下が冒頭だが、

```
{
	'messages': [],
	'customMessageFileName': None,
```

```
Error: Parse error on line 1:
{	'messages': [],	'cu
--^
Expecting 'STRING', '}', got 'undefined'
```
と言われる。
jsonについてよく分かってないので何が問題なのかが分からない。
undefinedと言われているので、何か未定義になっている気がする。
記述がおかしいのだろうか。

今はここから先が分からない。困った……。

##追記
そもそも吐き出されたjsonの記述形式がデコード前の状態なのではないかと思い至る。だって""で括ってないし、FalseもTrueもNoneもむき出しだとエラーになる。（どハマりしていた）

##次はデコード周りを見よう
とりあえず問題の切り分けが一歩前に進んだので、次はデコードした状態でこれなのか、それともデコード前だからこうなのかを調べたい。