【问题标题】:Is JSON data a string or a dictionary in Flask?JSON数据是Flask中的字符串还是字典?
【发布时间】:2020-07-15 02:55:36
【问题描述】:

这可能是一个愚蠢的问题,但我真的很困惑(我是新手)。我正在尝试制作一个接受 JSON 作为输入的 API,并且我正在使用 Flask。该 API 采用 POST 方法,因此当请求出现时,它会使用

从正文中获取 JSON 数据

data = requests.get_json()

我希望数据是一个字符串,因为如果我没记错的话,JSON 只不过是一个格式化的字符串。

所以,我这样做了data = json.loads(data) 但是,我的烧瓶应用程序崩溃了,因为它说数据是字典而不是字符串。当然,我可以通过不使用json.loads 来解决它,但这只是困扰我,我想知道为什么我得到的是字典而不是字符串。

这是我发送测试请求的方式,这让我很困惑

1)

import requests
import pandas as pd
data = pd.read_csv('some.csv')
data = data.iloc[[0]].to_json(orient='records') // get the first row into json
res = requests.post(url, json=data) // I get a string in my Flask app.
import requests
data = {'name':'foo','age':99}
res = requests.post(url, json=data) // I get a dictionary in my Flask app.
const xhr = new XMLHttpRequest();
const json = {'name':'foo','age':99};
xhr.open("POST",url);
xhr.setRequestHeader("Content-Type","application/json");
xhr.send(JSON.stringify(json)); // Though stringified, I get a dictionary in my Flask app. Why?

我不确定你是否能看出我的困惑。在某些情况下,我得到一个字典,而在其他一些情况下,我得到一个字符串。所以,我很困惑,不知道如何设计我的 API 和处理请求。 提前感谢您的关注!

【问题讨论】:

  • pandas.DataFrame.to_json 返回一个字符串。
  • data = json.loads(data) 接受一个字符串变量(数据)并将其转换为字典。
  • JSON 代表 JavaScript Object Notation - 一种将 JavaScript 对象序列化为遵循特定符号的字符串的方法。简而言之,JSON 确实是一个具有特定编码的字符串。您在此处遇到的一些 API 对于名称为 json 的方法应返回或接受作为参数的内容有不同的看法。
  • 接下来,您的问题实际上在于requests.post 如何处理json 参数 - 它会在提交请求之前隐式调用json.dumps 之类的东西,所以您的第一个示例是to_json已经是字符串的输出被双重编码为​​ JSON 字符串类型,其中包含底层对象(或 dict)的 JSON 编码。因此,当它到达接收该有效负载的端点时,它将正确解码并将其视为一个字符串(由to_json 生成的 JSON 编码有效负载)。

标签: python json dictionary flask python-requests


【解决方案1】:

Pandas 的 DataFrame.to_json 返回一个字符串 (str)。因此,在这段代码中

data = df.to_json(orient='records')
res = requests.post(url, json=data)

data 实际上是一个str 对象,将其传递给requests.postjson 参数会将该字符串编码为JSON再次。见

response = requests.post(url, json={"foo": 1})
print(response.request.body)

response = requests.post(url, json='{"foo": 1}')
print(response.request.body)

将打印

b'{"foo": 1}'
b'"{\\"foo\\": 1}"'

要正确发送 JSON 数据,您必须做的是

data = df.to_json(orient='records')
response = requests.post(url, data=data.encode())

或者实际上将DataFrame 转换为dict

data = df.to_dict(orient='records')
response = requests.post(url, json=data)

【讨论】:

  • 我想补充一点,requests.postjson 参数更适合dict 类型,而data 参数用于已经最终确定为预期形式的有效负载。
  • 确实,我编辑了我的答案,通过将DataFrame 转换为字典来添加另一个正确使用json 参数的解决方案。
【解决方案2】:

JSON 对象不过是 python 中的字典,flask 是 python 编写的框架
因此,json 库公开了用于将数据写入文件的 dump() 方法。还有一个 dumps() 方法(发音为“dump-s”)用于写入 Python 字符串。
根据相当直观的转换将简单的 Python 对象转换为 JSON。

Python          JSON
dict            object
list,tuple      array
str             string
int,long,float  number
True            true
False           false
None            null


所以取决于从 json 中提取的内容,python 变量的行为会相应地,
就像第一种情况一样
data = data.iloc[[0]].to_json(orient='records') 数据变量只不过是一个字符串,
所以这就是res = requests.post(url, json=data) 在这里显示这种行为的原因
在第二种情况下
data = {'name':'foo','age':99} 是字典
所以这就是为什么 res = requests.post(url, json=data) 表现出这样的行为

【讨论】:

    猜你喜欢
    • 2019-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    相关资源
    最近更新 更多