DifyのHTTPリクエストでJSONエラーが出たら、「JSONとして読めるか」「読み取った値の型が送信先の仕様に合うか」「APIがどう応答したか」を分けて確認します。引用符や改行を含む文章は、文字列を手でつなぐよりJSON用の処理で組み立てます。構文が正しくても、二重にJSON化するとObjectがStringになることがあります。

対象は、Difyで前のノードの結果をHTTPリクエストへ渡す練習中の人です。本稿は、架空の備品返却メモを使い、外部送信の前に本文を検査する教材です。実在の受付、メール送信、契約処理、課金APIの呼び出しは行いません。

仕様・講座情報の確認日:2026年10月11日。Dify公式HTTP Request、Python公式json、HTTPの標準仕様を参照しています。Dify公式ページの最終更新表示は2026年8月27日でした。本稿のコードはPython 3.12.14のローカル参照実行で確認し、Dify管理画面や外部APIで実行した結果とは区別しています。

まずJSONとして読めるか、次にObjectなどの型が合うかをローカルで確認し、実機ではAPI応答を別に確かめる。
スマホでは図を横にスクロールできます。編集部作成の確認図。本文の架空例を整理しています。

送信前に、JSONの構文と読み取られる型を確認する

エラーを出したノードと、相手が求める本文を先に特定する

「HTTPからJSONエラー」と聞いたときに、リクエスト本文が壊れているとは限りません。前のCodeノードで文字列を組み立てる処理、HTTPノードの本文設定、相手APIの入力検査、応答を読む後続処理という、複数の場所でJSONを扱うことがあります。まず実行履歴で止まったノードを確認します。

送信前に本文を読めなかった場合と、送信後に400を受け取った場合では、確認する情報が異なります。前者は構文や変数の値、後者はステータスコードと相手のエラー本文が入口です。APIから返ったHTMLを後続でJSONとして読もうとして失敗する場合も、リクエスト側の引用符を直すだけでは解決しません。

次に、送信先の公式API仕様で期待するトップレベルを確認します。Object一つを受け付けるのか、Objectの配列を受け付けるのか、JSON化されたStringを受け付けるのかを見ます。本稿はObjectを要求する仮想の仕様で練習します。実在のAPIの契約や入力仕様を再現したものではありません。

仮想仕様では、demo_idとmessageは文字列、quantityは整数、approvedは真偽値、dueは文字列またはnull、tagsは文字列の配列とします。これを一枚の表へ書き、生成する本文と比べます。画面で「0」「false」が見えることだけで、数値や真偽値が保たれているとは判断できません。

必須項目や長さ制限も別に扱います。空のmessageがJSONとして有効でも、API側が空欄を禁止していれば入力条件を満たしません。構文チェックの成功を、業務上の受付成功へ読み替えないでください。確認を段階に分けると、同じ入力を何度も送り直す前に原因を絞れます。

エラーを調べる三つの段階
段階確認する問いこの教材での方法
JSONの構文JSONとして読み取れるかjson.loadsで読み戻す
値と型Objectや各項目の型が期待どおりかdict・int・bool・None・listを照合
HTTPと相手の処理相手が受け付けたか実機ではステータス・応答本文・受付状態を確認

引用符・改行・バックスラッシュを含む7入力を用意する

日本語だけの短い文章で成功しても、引用符や改行のある文章で同じ結果になるとは限りません。担当者名を引用符で囲んだメモ、二行の確認文、フォルダーを表すバックスラッシュなど、日常の文章に含まれる文字を試します。実在の個人情報ではなく、架空の内容に置き換えて練習できます。

用意するのは、通常の文章、引用符、実際の改行、バックスラッシュ、空文字、タブ、絵文字の七種類です。改行は「バックスラッシュとnの二文字」を入力した場合と、文字として改行を含む場合で違うので、どちらを試したかを記録します。コードではPython文字列の\nを使って実際の改行を表します。

見比べるのは、JSONの画面上の形だけではありません。入力のmessageと、JSONを読み戻したmessageが同じ内容かを確認します。エスケープされたJSON文字列では改行が\nに見えても、読み戻した値に改行があれば内容は保たれています。見える記号が増えたことを、文章が壊れた証拠にしないでください。

空文字は、構文と業務ルールの違いを確かめるために含めます。JSONの文字列として空欄は有効ですが、備品返却の説明に必要なメモとしては不足するかもしれません。JSONを作る工程と、受付に必要な項目を検査する工程を、ここでも分けます。

絵文字は、日本語や記号が往復後に残るかを見る入力です。この教材で残ったからといって、相手APIの文字数制限や絵文字の受付まで確認できたわけではありません。送信先で扱える文字と、JSON化で文字を保持することは、それぞれ確認が必要です。

架空メモの7ケースと、読み戻した後の確認
ケース入力の特徴確認すること
J01備品を返却します日本語が一致
J02担当者は引用符付きの山田引用符が残る
J03確認済み/返却待ちの二行実際の改行が残る
J04保管場所AとBの間にバックスラッシュ一つの記号として残る
J05空文字空欄のまま。受付可否は別検査
J06先頭にタブのある要確認タブを含む元の文字列と一致
J07貸出機器と箱の絵文字文字が往復後も一致

文字列連結とjson.dumpsを、外部送信なしで比べる

JSONらしい形を作るために、文字列へ引用符を付けてつなぐと、入力側に引用符がある場合に境界が崩れます。例えば担当者は「山田」という内容を半角引用符で表した入力では、入力の引用符とJSONの区切りの引用符を区別する処理が必要です。日本語だけの例で通った書き方を、そのまま一般化しないでください。

次のコードは、辞書として組み立てたpayloadをJSON文字列へ変換し、読み戻した値と比べます。ネットワークへの送信は含みません。ensure_ascii=Falseは日本語を読みやすい表示へする指定で、引用符や改行の処理を省略する指定ではありません。

import json

messages = [
    "備品を返却します",
    '担当者は"山田"',
    "確認済み\n返却待ち",
    "保管場所 A\\B",
    "",
    "\t要確認",
    "貸出機器📦",
]

for message in messages:
    payload = {
        "demo_id": "J01", "message": message,
        "quantity": 0, "approved": False, "due": None,
        "tags": ["貸出", "返却"],
    }
    body = json.dumps(payload, ensure_ascii=False, allow_nan=False)
    parsed = json.loads(body)
    assert parsed == payload
    assert isinstance(parsed, dict)
    assert type(parsed["quantity"]) is int
    assert type(parsed["approved"]) is bool
    assert parsed["due"] is None
    assert isinstance(parsed["tags"], list)
print("7ケースの値と型が一致")

allow_nan=Falseは、NaNなどを含んだときに、そのまま通常のJSON本文として進めないための指定です。今回の架空入力にはNaNを含めていませんが、実データで数値変換後の欠損を混ぜる場合は扱いを決める必要があります。未知の金額を、理由なく0やnullへ変更する処理はこのコードに含めていません。

編集部の参照実行では、七つのmessageが読み戻し後も一致し、quantity、approved、due、tagsの型も保たれました。別に、引用符・実際の改行・不正なバックスラッシュを手で埋め込んだ三つの本文が、JSONDecodeErrorで拒否されることを確認しています。DifyのAPI受付成功率などの数値ではありません。

読み戻せたことを、相手へ送る必要がない練習の終了条件にできます。送信先がまだ決まっていない段階で、動作確認のためだけに公開APIや実在の業務APIへ投げる必要はありません。まずこの小さい入力で、文字列と型の関係を説明できるようにします。

二重エンコードは、正しいJSONでもObjectをStringに変える

JSON化したbodyをもう一度json.dumpsへ渡すと、JSON文字列そのものが文字列の値として包まれます。これも構文上は有効なJSONなので、JSONDecodeErrorが出ないことがあります。しかし、一度読み戻した結果はdictではなくstrになります。

payload = {"demo_id": "J01", "message": "備品を返却します"}
body = json.dumps(payload, ensure_ascii=False)
wrapped = json.dumps(body, ensure_ascii=False)

assert isinstance(json.loads(body), dict)
assert isinstance(json.loads(wrapped), str)

Objectを要求する仮想APIへwrappedを送ると、相手は必要なdemo_idをObjectの項目として取り出せません。「JSONバリデーターでは正常なのに、相手が受け付けない」という状況を、構文と型の二段階で説明できます。バリデーターの成功表示だけを最終判定にしない理由です。

ただし、あらゆる文字列化を一回へ減らすという意味ではありません。API仕様が「ある項目の中へJSON文字列を入れる」と定めているなら、その項目は文字列として扱う必要があります。本稿の仮想仕様ではトップレベルにObjectを要求しているので、トップレベルのStringは合わない、という範囲の説明です。

また、ログ表示が外側へ引用符やバックスラッシュを付ける場合があります。表示のためにエスケープされたログを見て、通信本文も二重エンコードされたと断定しないでください。実際に渡した値と、ログを表示する仕組みを区別し、送信先の試験環境で読み取った型を確認するのが次の段階です。

Difyの前工程がObjectを出しているのか、JSON文字列を出しているのかを記録します。後工程がObjectを受け取ってJSON化するのか、文字列を本文として使うのかまで確認できると、どの境界で変換が重なったかを見つけやすくなります。「JSON」という名前の変数だけでは型は分かりません。

0・false・null・配列を、引用符の有無まで確認する

数量0を"0"へ変えると、数値ではなく文字列です。承認フラグfalseを"false"へ変えても、文字列になります。見た目は似ていても、相手が整数や真偽値を要求していれば別の入力です。値が見えることと、型が合っていることを分けて確認します。

PythonのFalseはJSONではfalse、Noneはnullとして表されます。文字列の"None"や"null"と混ぜないようにします。JSONの本文へPython辞書をそのまま文字表示して貼ると、単一引用符やFalseなどが残り、JSONとして扱えない場合があります。辞書の表示とJSON化は異なる操作です。

tagsは文字列の配列です。["貸出", "返却"]を一つの文字列として入れるのか、二要素の配列として入れるのかで、相手の処理が変わります。カンマ区切りの見た目が同じでも、listとして読めるかを確認します。後続で配列を反復するなら、ここでの違いがエラーにつながります。

Pythonではboolがintの一種として扱われるため、この教材は数量の検査にtype(...) is intを使っています。整数0のつもりでFalseを渡した例を、数量の検査で見逃さないためです。実際のAPI仕様が整数以外も許容するなら、仕様に合わせて条件を変えます。

空文字とnullも異なります。「期日が未設定なのでnull」「期日欄へ空文字が入力された」という二つを、同じ値へまとめてよいかは業務上の判断です。JSONを作れるようにする目的だけで情報を消すのではなく、各状態の意味を決めてから入力検査へ反映します。

HTTP設定とAPIの応答を切り分けて、練習を仕上げる

本文タイプとヘッダーを、送信先の公式仕様へ合わせる

Dify公式はHTTP Requestノードの本文タイプとして、JSON、Form Data、Binary、Raw Textを案内しています。どれを使うかは相手のAPI仕様で選びます。外部連携の記事でJSONを使っていたから、別のAPIにも同じ設定を適用できるとは限りません。

JSONを要求するAPIなら、期待するObjectやArrayの形、Content-Type、必須項目を確認します。フォーム形式を要求するAPIへ、同じ項目名のJSONを送っても、相手が読み取る場所は違うことがあります。認証が成功したことと、本文の形式が受け付けられたことも分けて扱います。

最初は可変の文章を入れず、固定の架空Objectが仕様に合うかを確認します。次に短いmessageを変数へ置き換え、最後に引用符や改行を含む入力を試す順序にします。固定本文、変数の接続、特殊文字を一度に変えると、失敗した変更を絞れません。

ただし、試験送信する場合は、管理者が用意した試験環境と、送信が許可された架空データを使います。本稿は送信先URLや認証情報を配布していません。読者が実在の受付APIへそのままコピーして実行する例ではなく、入力検査の考え方を学ぶための教材です。

ヘッダーの確認時に、認証情報を本文や画面共有へ出さないようにします。設定内容を相談するなら、認証方式とヘッダー名、本文の型、エラー箇所など、値を伏せても原因を調べられる情報からまとめます。秘密の値を表示して確認する必要はありません。

変数の接続と、Dify実機で確認する範囲を明確にする

公式文書は、前のノードの変数をURL、ヘッダー、本文などへ動的に挿入できると案内しています。一方、利用しているCloud版や自己ホスト版の画面、前ノードの出力型によって、選択できる項目や表示が異なる可能性があります。ローカルPythonで確認したJSONを、そのままDifyで確認済みと扱わないでください。

本稿のコードはmain関数やDifyの出力変数宣言を含まない、通常のPython用です。Codeノードへ移す場合は、そのノードの入力・出力定義を公式仕様へ合わせる必要があります。Pythonのdictを返す出力と、json.dumpsで作ったstrを返す出力を区別します。

実機で見る項目は、前ノードの出力型、本文欄へ接続した変数、本文を作るモード、最終的に相手へ渡る形です。手入力した引用符の中へJSON文字列を入れていないか、前工程と後工程で同じJSON化が重なっていないかを確認します。自動で何がエスケープされるかは、実機で確かめる項目です。

古い記事に「Objectを一度Stringへ変えると変数候補へ出る」という対処があっても、現在の画面へ無条件で適用しません。候補が見えないときは、前ノードの型、ノードの接続、使用版、公式の入力条件を先に確認します。型を変えた結果、後続の期待するObjectを失っていないかも検査します。

実機の確認記録は、本文の生成方法、入力のケース番号、受け取った型、ステータス、相手の受付状態を分けて残します。教材の「七ケースが往復で一致」と、相手APIで「七件を正常受付」は異なる結果です。後者を確認していないなら、前者の範囲で報告します。

構文エラー・400・429・タイムアウトを別の原因として調べる

400は、相手が入力側の問題として処理できない応答で、JSONの構文だけを示すものではありません。必要項目がない、型が違う、形式が違うなど、相手のエラー本文で理由を調べます。400という数字だけから「引用符を消せば直る」と決めることはできません。

401や403では、認証やアクセス条件を確認します。本文を何度も変えても、利用者や権限が合わない問題は直りません。設定を共有する場合も、実際の認証値を見せるのではなく、方式や対象API、返ってきた説明を値を伏せた形で整理します。

429については、RFC 6585が一定時間内のリクエスト過多を表すコードとして定義しています。サービス独自の利用枠などを説明する場合もあるため、相手の本文と公式のエラー一覧を確認します。あらゆる429を「残高不足」と断定して課金へ進む説明は避けます。

5xxやタイムアウトは、構文の検査とは別に、相手の状態、接続、処理時間を調べる入口です。応答が返らなかったからといって、相手が何も処理していないとは限りません。受付や登録を行うAPIなら、再送前に既に受付済みかを確認する必要があります。

現象から、次に確認する場所を選ぶ
現象最初の確認成功と見なさないこと
JSONDecodeError組み立てた本文とエラー位置通信先の不具合と決めつけない
構文正常・型がString二重JSON化とトップレベルObjectの項目があると見なさない
400相手の入力仕様とエラー本文構文正常だけで受付成功にしない
401・403認証方式とアクセス条件本文の修正だけで直そうとしない
429利用頻度・応答説明・再試行条件残高不足だけを原因にしない
5xx・タイムアウト相手の状態と既存の受付失敗表示だけで未処理と決めない

外部送信なしの教材から、実務の確認と学習支援へ進む

最初の到達目標は、七入力をJSON化して読み戻し、値と型の一致を説明することです。次は、仮想仕様の必須項目や空欄の条件を追加し、不適合な入力を送信前に止める練習へ進めます。ここまでは実在のAPIや有料モデルを呼び出さずに学べます。

例えばmessageの空欄を禁止するなら、J05は構文正常でも入力条件不適合と記録します。quantityが0でも有効とするなら、単に「値があるか」という判定で0を弾かない条件が必要です。仕様を一つ加えるごとに、通るケースと止まるケースを先に書くと、目的に合う検査を作れます。

JSON本文をLLMへ修正させるより、入力の型と組み立てを決めて処理する方が、同じ結果を再現しやすい場面があります。自由文の意味を抽出する部分をAIに任せる場合でも、最終的な本文の構文や項目検査は別に置きます。AIが「正しいJSONです」と説明したことを検証結果にはしません。

学習支援を比較したい人は、JSONだけでなくノード間の接続やエラーの切り分けで止まっている人です。2026年10月11日に確認したバイテックのDifyマスターコースは、Difyによるアプリやワークフロー学習の候補です。本稿の七入力を受講者として試した体験談ではありません。

相談前には、HTTPノード、JSONの型、Codeノード、外部APIのエラーをどこまで質問できるか、利用ツールの追加費用、サポート期間、課題レビューの範囲を確認します。Difyを扱う講座だから、この個別APIとの連携まで支援対象だと断定しないでください。

公式のDify入門・ワークフロー編には、HTTPリクエストの基本を扱うレッスンが掲載されています。ただし、本稿の七入力のレビュー、利用中のAPIへの接続支援、個別のJSONエラー対応が含まれるとは確認していません。無料説明会では、質問できる範囲、サポート期間、講座の総費用と外部ツールの利用料を分けて確かめます。

PR:バイテックAIスクールの無料説明会を確認する

独学で進めやすいのは、入力と期待する型を小さく定義し、どこで違いが出たかを調べられる人です。相談したい場合は「エラーが出た」だけでなく、架空入力、前ノードの型、送信先が期待する型、値を伏せた応答をまとめます。学習方法を選ぶための判断材料になります。

FAQと、再試行する前の確認順序をまとめる

最後に、固定本文の構文、トップレベルの型、項目の型、変数を入れた後の本文、HTTP応答という順序で確認します。値と型が期待どおりなら、そこで初めて相手の試験環境へ進む条件を整理します。順番を決めると、毎回別の修正を試して原因を見失うことを減らせます。

Dify公式はHTTPノードにタイムアウト、再試行、失敗時の代替経路を案内しています。ただし、構文や型の不適合を再試行回数だけ増やして直すものではありません。同じ不適合な本文を送り直しても、必要な項目は追加されません。まず送信前の検査で止める場所を作ります。

登録処理を行う相手では、再送が二重登録につながるかを仕様で確認します。リクエスト識別子や重複防止をどこで扱うかは、相手APIによって異なります。仮想demo_idを入れたことだけで、実在のAPIに重複防止が実装されたとは判断できません。

エラーの整理メモは、「J02は引用符を含む入力。ローカルのJSON往復は一致。Dify前ノードはString。相手はObjectを要求。本文モードと変数挿入後の型は未確認」のように、確認済みと未確認を一緒に書けます。全部を一つの「JSONエラー」と呼ぶより、次の作業が明確になります。

本稿で確認したのは、七入力の値と型の一致、手入力した三つの不正構文の拒否、二重JSON化後のトップレベルがStringになることです。実在のAPIの成功応答や、Difyの特定版におけるエスケープ方式は、このローカル実行だけでは確認できません。使う画面と相手の仕様を合わせて仕上げます。

よくある質問

Q. JSONエラーを避けるために、改行を全部消す必要がありますか?
A.

この教材ではjson.dumpsで改行を含む文字列をJSON化し、読み戻した値が一致することを確認しています。相手が改行を許可するかは別の入力仕様です。意味のある改行を理由なく削る前に、JSON化と受付条件を分けます。

Q. JSONを文字列化するのは一回だけですか?
A.

Objectを期待する相手に対し、完成したJSON文字列をもう一度JSON化するとStringになる点に注意します。ただし項目内にJSON文字列を要求するAPIもあるので、相手が求めるトップレベルと項目の型で判断します。

Q. 構文が正常なのに400になるのはなぜですか?
A.

型の不一致、必須項目の欠落、相手の入力条件などが考えられます。400は構文だけのエラーコードではありません。相手のエラー本文と公式API仕様を確認します。

Q. Difyの変数候補にObjectが見えない場合は、Stringへ変えればよいですか?
A.

古い画面の対処を無条件で適用せず、前ノードの出力型、接続、本文モード、使用版を確認します。型を変えたら、後続が期待するObjectやArrayが保たれるかも検査します。

Q. 429は残高不足を意味しますか?
A.

一般的には一定時間内のリクエスト過多を表すコードです。サービス固有の利用枠などもあり得るため、応答本文と相手の公式エラー説明で原因を調べます。コードだけから課金が必要と判断しません。

次に読む記事: