本文へスキップ
jsonbeautifiers
日本語
Python CPython 3.14.3 上でパーサーを実行して確認しました。

Expecting value: line 1 column 1 (char 0)

Pythonは、渡されたものの最初の1文字がJSONの値の始まりになっていない、と言っています。実際のところ、これがJSONの微妙な書式ミスを意味することはほとんどありません。パースした対象がJSONではないということです。HTMLのエラーページ、空のボディ、平文のメッセージ、あるいは何もない。位置が「行1、列1」なのは、パーサーが何も読まないうちに失敗したからです。

次のような書き方で見かけることもあります

  • json.decoder.JSONDecodeError: Expecting value

V8は2022年に、JSONのエラーメッセージのほとんどを書き換えました。検索結果に出てくるのはいまだに古い文言がほとんどですが、現行のランタイムはどれもそれを出力しません。

JSONを貼り付けて、壊れている箇所を正確に確認する

入力

貼り付けたものがブラウザの外に出ることはありません。 connect-src の許可リストにより、これは約束ではなくブラウザによる保証になっています。 自分で確かめる

実際の原因

どれが答えになることが多いか、その順に並べています。

  1. 01 レスポンスのボディがJSONではなくHTML

    404ページ、ログインへのリダイレクト、Cloudflareのチャレンジ、プロキシのエラーページなどです。HTTPのレベルではリクエストは成功し、ドキュメントも返ってきています。期待したものではなかっただけです。パースする前に先頭の数百文字を出力すれば、すぐに分かります。

    壊れる例

    r = requests.get(url)
    data = r.json()   # JSONDecodeError

    動く例

    r = requests.get(url)
    if r.status_code != 200 or 'json' not in r.headers.get('content-type', ''):
        raise RuntimeError(f"{r.status_code} {r.headers.get('content-type')}: {r.text[:300]}")
    data = r.json()
  2. 02 ボディが空

    HTTP 204、レート制限で何も返らなかったリクエスト、ボディを落としたWAF、あるいは存在するが0バイトのファイルなど。空文字列は妥当なJSONではありません。もっとも短い妥当なドキュメントは null、0、""、[]、{} です。

    壊れる例

    json.loads("")

    動く例

    text = r.text
    if not text.strip():
        return None
    data = json.loads(text)
  3. 03 JSONではないファイルを読んでいる

    CSV、ログファイル、Pythonのpickle、あるいは各行が別々のドキュメントであるJSON Linesファイルなど。JSON Linesの場合は、一括ではなく1行ずつパースしてください。

    壊れる例

    with open('events.jsonl') as f:
        data = json.load(f)   # Expecting value, or Extra data

    動く例

    with open('events.jsonl') as f:
        data = [json.loads(line) for line in f if line.strip()]
  4. 04 認証に失敗し、APIが平文のメッセージを返した

    多くのAPIは401や403とともに「Unauthorized」や「Forbidden」をJSONではなく平文で返します。ボディを見る前にステータスコードを確認してください。

ほかのランタイムでの同じ間違い

根本にある問題は同一で、違うのは文言だけです。同僚がこれらのどれかを報告してきたなら、見ているものはあなたと同じです。

JavaScript (V8) Unexpected token '<', "<!DOCTYPE "... is not valid JSON
JavaScript (V8), empty input Unexpected end of JSON input
C# (Newtonsoft) Unexpected character encountered while parsing value: <. Path '', line 0, position 0.

よくある質問

なぜいつも「行1、列1」なのですか?
パーサーが最初の1文字で失敗したからです。2行目に到達するところまで進んでいません。もしエラーがもっと後ろの行と列を示しているなら、問題は本当にあなたのJSONの中にあり、それは別のエラーです。
実際に受け取った内容を確認するには?
.json()を呼ぶ前に response.text[:500] を出力してください。10回のうち9回は、最初の1行で答えが分かります。<!DOCTYPE html>、空文字列、あるいは短い平文のメッセージです。
json.loadsはbytesオブジェクトを受け取れますか?
受け取れます。Python 3.6以降、json.loadsはstrに加えてbytesとbytearrayを受け付け、UTF-8、UTF-16、UTF-32を判別します。したがってこのエラーの原因がbytesを渡したことである、ということはありません。

今すぐ直す

上のツールにペイロードを貼り付けるか、この用途のために作られたツールに直接進んでください。

JSONを検証する