将“true”(JSON格式)转换为Python等效的“True”。

67

我最近使用的列车状态API在JSON对象中添加了两个额外的键值对(has_arrived,has_departed),这导致我的脚本崩溃。

以下是词典:


{
"response_code": 200,
  "train_number": "12229",
  "position": "at Source",
  "route": [
    {
      "no": 1,
      "has_arrived": false,
      "has_departed": false,
      "scharr": "Source",
      "scharr_date": "15 Nov 2015",
      "actarr_date": "15 Nov 2015",
      "station": "LKO",
      "actdep": "22:15",
      "schdep": "22:15",
      "actarr": "00:00",
      "distance": "0",
      "day": 0
    },
    {
      "actdep": "23:40",
      "scharr": "23:38",
      "schdep": "23:40",
      "actarr": "23:38",
      "no": 2,
      "has_departed": false,
      "scharr_date": "15 Nov 2015",
      "has_arrived": false,
      "station": "HRI",
      "distance": "101",
      "actarr_date": "15 Nov 2015",
      "day": 0
    }
  ]
}

毫不意外,我收到了以下错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'false' is not defined

如果我没有弄错的话,我认为这是因为JSON响应中的布尔值为false/true,而Python识别的是False/True。 有什么解决方法吗?

附注:我尝试将has_arrived的JSON响应转换为字符串,然后再将其转换回布尔值,但发现只要字符串中有任何字符,我就会始终得到一个True值。 我有点卡在这里了。


请问您能分享一下处理这个响应的代码吗? - Mureinik
你可以事先使用 sed 处理 JSON。 - jgyou
https://docs.python.org/dev/library/json.html - Andrea Corbellini
@JGab:为什么?这是JSON,不是Python。 - Martijn Pieters
是的,在事后看来那真是相当愚蠢。 - jgyou
这是 JSON 而不是 Python,所以你可能不想这样做,但你可以定义 false = None - NeilG
8个回答

78
尽管Python的对象声明语法非常类似于Json语法,但它们是不同且不兼容的。除了True/true的问题外,还有其他问题(例如,Json和Python处理日期的方式非常不同,而Python允许单引号和注释,而Json则不允许)。 解决方法不是尝试将它们视为相同的东西,而是根据需要从一种格式转换为另一种格式。 Python的本地json库可用于解析(读取)字符串中的Json并将其转换为Python对象,而且您已经安装了它...
# Import the library
import json
# Define a string of json data
data_from_api = '{"response_code": 200, ...}'
data = json.loads(data_from_api)
# data is now a python dictionary (or list as appropriate) representing your Json

你也可以将Python对象转换为JSON...

data_as_json = json.dumps(data)

例子:

# Import the json library
import json

# Get the Json data from the question into a variable...
data_from_api = """{
"response_code": 200,
  "train_number": "12229",
  "position": "at Source",
  "route": [
    {
      "no": 1, "has_arrived": false, "has_departed": false,
      "scharr": "Source",
      "scharr_date": "15 Nov 2015", "actarr_date": "15 Nov 2015",
      "station": "LKO", "actdep": "22:15", "schdep": "22:15",
      "actarr": "00:00", "distance": "0", "day": 0
    },
    {
      "actdep": "23:40", "scharr": "23:38", "schdep": "23:40",
      "actarr": "23:38", "no": 2, "has_departed": false,
      "scharr_date": "15 Nov 2015", "has_arrived": false,
      "station": "HRI", "distance": "101",
      "actarr_date": "15 Nov 2015", "day": 0
    }
  ]
}"""

# Convert that data into a python object...
data = json.loads(data_from_api)
print(data)

以下是第二个示例,展示了 True/true 转换的方式。请注意引号的变化以及注释的去除...

info = {'foo': True,  # Some insightful comment here
        'bar': 'Some string'}

# Print a condensed representation of the object
print(json.dumps(info))

> {"bar": "Some string", "foo": true}

# Or print a formatted version which is more human readable but uses more bytes
print(json.dumps(info, indent=2))

> {
>   "bar": "Some string",
>   "foo": true
> }

我不知道我是否完全理解你所说的,但是,正如你所回答的那样,当我尝试初始化data_from_api变量时,它给出了相同的错误(名称false未定义)。所以我将字典初始化为字符串(data_from_api='<dict>'),然后使用了loads函数,它按预期工作。我想知道的是,我从api获取的字典非常大(为了简单起见,我在问题中缩小了大小),这是最有效的方法吗? - Jarwin
问题是您有一个包含Json的字符串,并且您将其视为包含Python的字符串。这两者并不相同。data_from_api应该是一个包含您在问题中发布的内容的字符串。您从文件还是通过Http请求读取此字符串取决于数据源,而您在问题中未指定。json库将把Json字符串转换为Python对象,反之亦然。 - Basic
我添加了一个示例,其中提供的数据被视为多行字符串文字。这样做是否使事情更清晰?("""..."""是定义跨越多行并包含 " 的字符串的一种方式)。一旦您有一个包含json的变量,转换就很简单了。如何填充该变量将取决于您获取数据的位置。下次,包括该信息/代码片段在问题中会很有帮助。 - Basic
我想再补充一件事,这对于从文件中读取数据的人很有用。with open('/Users/mohammed/Desktop/working_create_order.json') as jsonfile: data = json.dumps(jsonfile.read()) 然后按照上面的答案操作,即 data_json = json.loads(data) - mohammed_ayaz
使用推导式可以得到所有为True的值(todos是一个字典列表): sum([x["completed"] for x in todos]) 但如何得到所有为False的值呢? - Max Kleiner
1
我喜欢谷歌这个问题并进入这个SO页面,只发现在过去的某个时刻,我点赞了这个问题和答案。我相信这是我第四次访问这个页面,希望我能给它更多的赞。 - ingernet

9

你也可以使用值进行布尔类型转换。例如,假设你的数据叫做 "json_data":

value = json_data.get('route')[0].get('has_arrived') # this will pull "false" into *value

boolean_value = bool(value == 'true') # resulting in False being loaded into *boolean_value

虽然有点hackey,但它能够正常运行。


5

不要对答案使用eval,而是使用json模块。


5

Python中的布尔值可以应用于int、str、list等数据类型。

例如:

bool(1)     # True
bool(0)     # False

bool("a")   # True
bool("")    # False

bool([1])   # True
bool([])    # False

在 JSON 文件中,您可以设置:
"has_arrived": 0,

然后在您的Python代码中:

if data["has_arrived"]:
    arrived()
else:
    not_arrived()

这里的问题在于不要混淆表示False的0和其数值为0的0。


3
"""
String to Dict (Json): json.loads(jstr)
Note: in String , shown true, in Dict shown True
Dict(Json) to String: json.dumps(jobj) 
"""    
>>> jobj = {'test': True}
>>> jstr = json.dumps(jobj)
>>> jobj
{'test': True}
>>> jstr
'{"test": true}'
>>> json.loads(jstr)
{'test': True}

-1

我想再补充一件事情,这对于那些从文件中读取内容的人也适用。

with open('/Users/mohammed/Desktop/working_create_order.json')as jsonfile:
            data = json.dumps(jsonfile.read())

然后按照上面被接受的答案进行操作,即:

data_json = json.loads(data)

-3

json.loads无法解析Python的布尔类型(False,True)。Json希望使用小写字母false,true

我的解决方案:

python_json_string.replace(": True,", ": true,").replace(": False,", ": false,")


1
它无法正常工作,因为它用索引[0]、[1]等替换了键。 - Caio Wilson

-3

3
如何 { "key": false } 不是有效的 JSON? - Javed Sayyed
因为它可以从文件中读取。在这种情况下,两者都应被视为字符串。 - Shravya Boggarapu
1
你说 { "key": false } 不是有效的 JSON,并提供了一个验证器链接,但该链接显示它是有效的。你能详细说明一下吗? - Mulperi
这是错误的,https://www.w3schools.com/js/js_json_datatypes.asp 和 https://www.json.org/json-en.html 都明确表示布尔值是被允许的。 - Luk164
只是一个错误的答案。 - Masoud Dadashi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接