json.loads与ast.literal_eval

357 阅读2分钟

今天在尝试把一个列表格式的字符串用json.loads转换成列表的时候报错了,字符串的格式be like:

string1 = "['a','b','c','d']"

报错信息为:json.decoder.JSONDecodeError 查阅资料后发现如果要对字符串进行json解码,该字符串的格式必须为正经的json编码格式,也就是说,只能是双引号,不可以是单引号。所以,如果想用json.loads(string),string 就必须是这样:

string2 = '["a","b","c","d"]'

说到json.loads,我们再浅延伸一下json函数。

函数描述
json.dumps将 Python 对象编码成 JSON 字符串
json.loads将已编码的 JSON 字符串解码为 Python 对象
json.load接受一个文件对象并返回 json 对象

那如果,给定的字符串就是string1该怎么办呢?也有办法,使用ast.literal_eval(string)就可以解决问题。我们先点进函数看一下这个方法:

def literal_eval(node_or_string):
    """
    Safely evaluate an expression node or a string containing a Python
    expression.  The string or node provided may only consist of the following
    Python literal structures: strings, bytes, numbers, tuples, lists, dicts,
    sets, booleans, and None.
    """

安全地计算表达式节点或包含Python表达式的字符串。后面给出了可供转换的字符串或节点的类型。它会判断需要计算的内容计算后是不是合法的python类型,如果是则进行运算,否则就不进行运算,这一点就体现了该方法的安全性。

其实python中还有一个强大的字符串转换方法eval,先看一下它的方法介绍:

def eval(*args, **kwargs): # real signature unknown
    """
    Evaluate the given source in the context of globals and locals.
    
    The source may be a string representing a Python expression
    or a code object as returned by compile().
    The globals must be a dictionary and locals can be any mapping,
    defaulting to the current globals and locals.
    If only globals is given, locals defaults to it.
    """

eval函数可以把数据还原成它本身或者是能够转化成的数据类型,例如string与list,tuple,dict之间的类型转换,甚至可以做计算器用,比如:

print(eval('1+1'))

结果就会打印2。

但功能功能如此强大的eval是存在很大的安全隐患的,尤其是当传入的字符串为用户输入的时候,如果有用户恶意输入删除文件等表达式,你的文件就真的会被格式化。关于eval具体的安全隐患,大家可以自行食用。

所以,安全起见,我们还是用ast.literal_eval,当字符串为json格式时,用json.loads也是极好的。

参考:

www.cnblogs.com/wangbin2188… www.runoob.com/python/pyth…