質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

3395閲覧

JsonのダブルクォーテーションがシングルクオーテーションになりJsonが形式不正になる

XYZ

総合スコア2

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2022/09/02 11:25

前提

pythonで CSVを読んでOracle DBに登録したり、Oracle RestAPI を使い、ERPとOracle DBで受け渡しを行ったりしておます

実現したいこと

以下のような感じのJsonをrequests.postでPostしているのですが、
今作成中のものについてはjson内のダブルクォーテーションがシングルクオーテーションに変わってしまいJsonが正しくない状態になってしまいます。(下記 注①のような結果が返ってきます) 

Postmanでシングルクオーテーションをダブルクォーテーションに変換したJsonをRawで渡すとCreatedとなりERPに登録されるのですが、Pythonのプログラムからだと登録されない状態です。 

値がエスケープされると参照性整合性制約的にある項目がペイロードエラーになるためjson.dumpなどで変換はしないようにしています。

整形サイトでもJsonを貼ると正しいJSON形式ではありませんとなり、シングルクオーテーションをダブルクォーテーションに変換したJsonを設定すると正しいJsonとして判定され整形されます

どなたかJsonの’をダブルクォーテーションにする方法を教えてください
よろしくお願いします

注①
ステータス 400
Unable to parse the provided payload ( 提供されたペイロードを解析できません )

{
'TestKomoku': '0001',
'TestKomokuName': 'テスト',
'CreationDate': '2022-06-29T00:00:00.00+00:00',
'serials': [
{
'FmSerialNumber': 'UC1913_I000038',
'ToSerialNumber': 'UC1913_I000038'
}
]
}
→ プログラムでは全て ” で設定しているのに Jsonを出力すると ” が ’ に変換された状態になっています

発生している問題・エラーメッセージ

Unable to parse the provided payload ( 提供されたペイロードを解析できません

該当のソースコード

Python

1ソースコード

import requests
import json

#jsonのセットなど省略

headers = {'content-type': 'application/json'}
print (json_data)
r = requests.post(url, json_data, headers=headers)
print(r.status_code)

試したこと

string.replace("'", '"') → jsonが dict型なのでNG

json_list =[string.replace("'", '"') for string in json_data]
→ 変化なし

補足情報(FW/ツールのバージョンなど)

Python 3.9.12 Anaconda(Miniconda)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2022/09/02 11:37

> 値がエスケープされると > json.dumpなどで変換はしないようにしています。 ensure_ascii=Falseとしてもダメですか?
otn

2022/09/02 11:55

json_dataは何ですか?中身の意味では無くて形式を聞いています。 JSON(str型)じゃなくてdict型では?
XYZ

2022/09/02 13:19 編集

json.dump で ensure_ascii=False するとエラーになってしまいます。 以下のような感じで記載してもこちらの環境ではエラーになります。 with open("xxx.csv", "w", encoding="utf-8") as outputFile: json.dump(dict, outputFile, indent=2, ensure_ascii=False )     ↓   json.dump(json_data, outputFile, indent=2, ensure_ascii=False )  の誤りです
XYZ

2022/09/02 12:11

json_dataはdict型です
meg_

2022/09/02 12:38

> こちらの環境ではエラーになります。 どのようなエラーですか?
XYZ

2022/09/02 12:45

以下のようなエラーになります File "c:\xxx\***.py", line 912, in main json.dump(dict, outputFile, indent=2, ensure_ascii=False ) File "C:\Users\***\Miniconda3\lib\json\__init__.py", line 179, in dump for chunk in iterable: File "C:\Users\***\Miniconda3\lib\json\encoder.py", line 438, in _iterencode o = _default(o) File "C:\Users\***\Miniconda3\lib\json\encoder.py", line 179, in default raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type type is not JSON serializable TypeError: タイプ type のオブジェクトは JSON シリアライズ可能ではありません
XYZ

2022/09/02 12:53

postmanで実行した際に 日本語部分がエスケープされていないJsonをraw jsonとして渡すとエラーなしのCREATEDになり、日本語部分がエスケープされたJsonをraw jsonとして渡すとある項目が無効のPyloadエラーになります。 ensure_ascii=False が効いて日本語部分がエスケープされなくなればpythonでもうまくいく動作すると思われる状態です
otn

2022/09/02 13:07

> json.dump(dict, outputFile, indent=2, ensure_ascii=False ) は、このまま書いているのですか? dict は型名ですが。json_data では?
quickquip

2022/09/02 13:08

情報は質問を編集して書いてください。
XYZ

2022/09/02 13:41

json.dump(json_data, outputFile, indent=2, ensure_ascii=False )  の誤りでした。
guest

回答1

0

ベストアンサー

json_dataはdict型です

JSONという言葉の意味を理解していないのでは?

Python

1a = {"abc":"x", "def":"y"} 2b = '{"abc":"x", "def":"y"}'

abはそれぞれJSONですか、違いますか?

postの第二引数にdict型、例えば{"abc":"x", "def":"y"}を指定すると、formのデータのように、
'abc=x&def=y'と変換されて送信されます。
JSONデータ、つまり'{"abc":"x", "def":"y"}'を送りたいのなら、
requests.post(url, json.dumps(json_data), headers=headers)
か、
requests.post(url, json=json_data, headers=headers)
と書きます。

値がエスケープされると参照性整合性制約的にある項目がペイロードエラーになるためjson.dumpなどで変換はしないようにしています。

は意味がわかりませんが、コメントで指摘のあるような非ASCII文字の話ですか?違うなら何の話ですか?

冒頭の正解は「bがJSON」です。

投稿2022/09/02 12:49

otn

総合スコア86293

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

XYZ

2022/09/02 14:11 編集

r = requests.post(url, json =json_data, headers=headers) → ( r = requests.post(url, json = "'{0}'".format(json_data), headers=headers) に修正しました) に修正すると 結果のr.statusは500、r.textはなし で返ってくるようになりました なぜステータスが500で返ってきているのか現在のところ不明ですが、ERP側でデータができているのであれば 別問題があるにせよ本事象はひとまず解決となります。 ありがとうございました。 400: 【HTTP 400 Bad Request】 500: 【HTTP 500 Internal Server Error】
otn

2022/09/02 14:08

> r = requests.post(url, json = json.dumps(json_data), headers=headers) と書いたのは、私の回答をちゃんと読んでないのでしょうか? まあ、この間違いでの害はないですが。 また、DBが更新されて、かつ、500エラーなのであれば、DB更新後に何らかのエラーが発生しているのでしょうね。 エラーログは見てませんか?
XYZ

2022/09/02 14:18 編集

TRY ~EXCEPTIONをいたるところで入れているのですが 例外エラーは補足されず、ステータスが500で返ってきています。すでにERP側でCREATEDされているから500だったらいいのですが・・・
otn

2022/09/02 14:24

先のコメントの「エラーログ」というのはサーバー側のエラーログのことです。 サーバー側のエラーログを見られない環境なのでしょうか? > TRY ~EXCEPTIONをいたるところで入れているのですが  一般論ですが、問題が発生して原因を調べているときにそんなことしちゃ駄目です。 例外処理はPython処理系に任せて得られる情報は全部得ないと。
XYZ

2022/09/02 14:29

json = "'{0}'".format(json_data)を出力すると '{'XXX': '111', 'YYY': 'テスト', 'CCC': [{'FromDDD': '555', 'ToDDD': '555'}]}'  となっており、中身がシングルクォーテーションになっているため内部的にエラーになっていました https://tools.m-bsys.com/development_tooles/json-beautifier.php などの整形サイトでも 正しいJSON形式ではありません。ではじかれてしまいます。 ダブルクォーテーションであれば正しいjSONとして認識されます
XYZ

2022/09/02 14:38 編集

post先のサーバーがOracle ERP Cloud環境でしかもssh転送で多段になっているためサーバーのログが確認できていません。 dbサーバなら確認できるのですが、Oracle ERP Cloud環境のログはリモート接続が解放されておらず、ERP Cloud環境しか接続確認できないので、Oracle ERP Cloud環境のサーバログが確認できない状態です
otn

2022/09/02 14:38

> json = "'{0}'".format(json_data) それではJSONに出来ません。JSON化とは全く関係ない処理です。 json = json.dumps(json_data) です。
XYZ

2022/09/02 14:48 編集

json = json.dumps(json_data)  だと '{'XXX': '111', 'YYY': '\*\*\*', 'CCC': [{'FromDDD': '555', 'ToDDD': '555'}]}' のような感じで日本語部分がエスケープというかサニタイジング(無害化)・エンコードされてしまい、 status 400 Invalid attribute "ZZZ" in the payload. という感じで、ステータスが400で、ある項目のエラー(ペイロードエラー)が返る状態になってしまいます エスケープされるとデータ同士の紐づけが結び付かなくなるようです。 (上で書いた通り、postmanで実行した際に日本語部分がエスケープされていないJsonをraw jsonとして渡すとエラーなしのCREATEDになり、日本語部分がエスケープされたJsonをraw jsonとして渡すとある項目が無効のPyloadエラーが返ります)
XYZ

2022/09/02 15:10

Print(”{0}".format(json_data).replace("'", '"')) で json_data内のシングルクォーテーションがダブルクォーテーションに変換されていることが確認できました
otn

2022/09/02 15:32

そのための ensure_ascii=False では? > Print(”{0}".format(json_data).replace("'", '"')) データの中に 引用符が出てこないのであれば、それも有りですね。あと True/False/Noneが出てくるなら書き換えないと。出てくるデータが限定的なら自分でJSON化を書くのも十分可能でしょう。
XYZ

2022/09/02 15:51

気づかなかったのですが json.dump と json.dumps という関数があるのですね  動作しない原因がわかりました。
otn

2022/09/02 16:41

> json.dump と json.dumps ウェブに投げるのに、何故いったんファイルに書くんだろうか?と不思議に思ってました。 dumpsを知らなかったんですね。
XYZ

2022/09/02 16:48

はい。 辞書型をJSON形式でファイルに出力する:json.dump( ) 辞書型を文字列に変換する:json.dumps( ) を一緒くたにしてしまい、ともに json.dump としてしまっていました ensure_ascii=False が動作しなかったのは json.dump  で指定していたからであり json.dumpsで指定すれば動作しました。 違いに気づきませんでした。 
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問