python解析json⽂件
JSON建构于两种结构:
“名称/值”对的集合(A collection of name/value pairs)。不同的语⾔中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
值的有序列表(An ordered list of values)。在⼤部分语⾔中,它被理解为数组(array)。
这些都是常见的数据结构。事实上⼤部分现代计算机语⾔都以某种形式⽀持它们。这使得⼀种数据格式在同样基于这些结构的编程语⾔之间交换成为可能。
下⾯是json格式的简单例⼦(来⾃百度百科):
按照最简单的形式,可以⽤下⾯这样的 JSON 表⽰”名称 / 值对”:
{"firstName":"Brett"}
这个⽰例⾮常基本,⽽且实际上⽐等效的纯⽂本”名称 / 值对”占⽤更多的空间:
但是,当将多个”名称 / 值对”串在⼀起时,JSON 就会体现出它的价值了。⾸先,可以创建包含多个”名称 / 值对”的 记录,⽐如:{"firstName":"Brett","lastName":"McLaughlin","email":"aaaa"}
从语法⽅⾯来看,这与”名称 / 值对”相⽐并没有很⼤的优势,但是在这种情况下 JSON 更容易使⽤,⽽且可读性更好。例如,它明确地表⽰以上三个值都是同⼀记录的⼀部分;花括号使这些值有了某种联系。
表⽰数组
当需要表⽰⼀组值时,JSON 不但能够提⾼可读性,⽽且可以减少复杂性。例如,假设您希望表⽰⼀个⼈名列表。在XML中,需要许多开始标记和结束标记;如果使⽤典型的名称 / 值对(就像在本系列前⾯⽂章中看到的那种名称 / 值对),那么必须建⽴⼀种专有的数据格式,或者将键名称修改为 person1-firstName这样的形式。
如果使⽤ JSON,就只需将多个带花括号的记录分组在⼀起:
{
"people":[
{"firstName":"Brett","lastName":"McLaughlin","email":"aaaa"},
{"firstName":"Jason","lastName":"Hunter","email":"bbbb"},
{"firstName":"Elliotte","lastName":"Harold","email":"cccc"}
]
}
这不难理解。在这个⽰例中,只有⼀个名为 people的变量,值是包含三个条⽬的数组,每个条⽬是⼀个⼈的记录,其中包含名、姓和电⼦邮件地址。上⾯的⽰例演⽰如何⽤括号将记录组合成⼀个值。当然,可以使⽤相同的语法表⽰多个值(每个值包含多个记录):
{
"programmers": [{
"firstName": "Brett",
"lastName": "McLaughlin",
python怎么读取json文件
"email": "aaaa"
}, {
"firstName": "Jason",
"lastName": "Hunter",
"email": "bbbb"
}, {
"firstName": "Elliotte",
"lastName": "Harold",
"email": "cccc"
}],
"authors": [{
"firstName": "Isaac",
"lastName": "Asimov",
"genre": "sciencefiction"
}, {
"firstName": "Tad",
"lastName": "Williams",
"genre": "fantasy"
}, {
"firstName": "Frank",
"lastName": "Peretti",
"genre": "christianfiction"
}],
"musicians": [{
"firstName": "Eric",
"lastName": "Clapton",
"instrument": "guitar"
}, {
"firstName": "Sergei",
"lastName": "Rachmaninoff",
"instrument": "piano"
}]
}
这⾥最值得注意的是,能够表⽰多个值,每个值进⽽包含多个值。但是还应该注意,在不同的主条⽬
(programmers、authors 和musicians)之间,记录中实际的名称 / 值对可以不⼀样。JSON 是完全动态的,允许在 JSON 结构的中间改变表⽰数据的⽅式。
在处理 JSON 格式的数据时,没有需要遵守的预定义的约束。所以,在同样的数据结构中,可以改变表⽰数据的⽅式,甚⾄可以以不同⽅式表⽰同⼀事物。
表⽰object
{
"name":"test",
"type":{
"name":"seq",
"parameter":["1","2"]
}
}
其中type属性是⼀个object,也就是属性嵌套。
Python2.6开始加⼊了json模块,⽆需另外下载,Python的Json模块序列化与反序列化的过程分别是 encoding和 decoding encoding(编码):把⼀个Python对象编码转换成Json字符串
decoding(解码):把Json格式字符串解码转换成Python对象
对于简单数据类型(string、unicode、int、float、list、tuple、dict),可以直接处理。
Encoding
python提供了两种函数来实现编码过程:
json.dump()和json.dumps(),其中dump()函数是⽤作⽂件操作,将在后⾯介绍,这⾥仅介绍dumps()。
下⾯看⼀个例⼦:
import json as js
obj = [{'aa': 1, 'bb': 2, 'cc': 3},
(1, 2, 3, 4), 'hello world', 0.5, 100, None, True]
print obj
print js.dumps(obj)
#output
[{'aa': 1, 'cc': 3, 'bb': 2}, (1, 2, 3, 4), 'hello world', 0.5, 100, None, True]
[{"aa": 1, "cc": 3, "bb": 2}, [1, 2, 3, 4], "hello world", 0.5, 100, null, true]
我们可以看到得到的输出原数据和类似,但是还是有些细微的不同,例如上例中的元组则转换为了列表。在json的编码过程中,会存在从python原始类型向json类型的转化过程,具体的转化对照如下:
Decoding
同样,json模块提供了json.load和json.loads两个函数来实现解码,load()函数⼀般⽤来读取json⽂件,下⾯先介绍json.loads函数。、
import json as js
obj = [{'aa': 1, 'bb': 2, 'cc': 3},
(1, 2, 3, 4), 'hello world', 0.5, 100, None, True]
tmp = js.dumps(obj)
x = js.loads(tmp)
print tmp
print x
print type(x)
#output
[{"aa": 1, "cc": 3, "bb": 2}, [1, 2, 3, 4], "hello world", 0.5, 100, null, true]
[{u'aa': 1, u'cc': 3, u'bb': 2}, [1, 2, 3, 4], u'hello world', 0.5, 100, None, True]
<type 'list'>
loads⽅法返回了原始的对象,但是仍然发⽣了⼀些数据类型的转化。⽐如,上例中‘aa’转化为了unicode类型。从json到python的类型转化对照如下:
以上是对简单类型的编码解码过程。另外需要注意的是,在编码过程中,默认的设置下,编码产⽣的json字符串过于紧凑导致可读性不⾼,
另外也没有顺序,为了提⾼可读性,dumps函数提供其他⼀些可选参数,下⾯介绍⼀些常⽤的参数:
dumps函数的定义为:
json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8"
1) skipkeys:布尔型,默认为False,如果设为True的话,在dict中的key值如果出现⾮ (str, unicode, int, long, float, bool, None)对
象,则跳过该key⽽不是抛出 ValueError。
2) indent:⾮负整数,表⽰编码后的字符串的缩进⽅式,默认为None表⽰⽆缩进,⼀般设为4,如果设为0则只会添加换⾏符。
3) separators:元组,默认为None,如果设置的话,⼀般设为(’,’,’:’),表⽰把’,’和‘:’后⾯的空格去掉,⽤来精简输出字符
串。
4) sort_keys: 布尔型,默认为False,如果设为True,则输出的dict会按照key值排序。
import json as js
obj = [{'aa': 1, 'bb': 2, 'cc': 3},
(1, 2, 3, 4), 'hello world', 0.5, 100, None, True]
print'Original:', js.dumps(obj)
print'Sort Keys:', js.dumps(obj, sort_keys=True)
print'Indent:', js.dumps(obj, indent=4)
print'Separators:', js.dumps(obj, separators=(',', ':'))
#Output
Original: [{"aa": 1, "cc": 3, "bb": 2}, [1, 2, 3, 4], "hello world", 0.5, 100, null, true]
Sort Keys: [{"aa": 1, "bb": 2, "cc": 3}, [1, 2, 3, 4], "hello world", 0.5, 100, null, true]
Indent:
[
{
"aa": 1,
"cc": 3,
"bb": 2
},
[
1,
2,
3,
4
]
,
"hello world",
0.5,
100,
null,
true
]
Separators: [{"aa":1,"cc":3,"bb":2},[1,2,3,4],"hello world",0.5,100,null,true]
以上都是json对简单数据类型的编码解码,那么如何对⾃定义的类型进⾏编码呢。默认情况下,json是不认识⽤户⾃⼰定义的类型的,这时
会抛出⼀个TypeError。如果要让json能编码⾃⼰定义的类型,需要⾃⼰定义⼀个转化函数,将MyObj转化成dict,然后在调⽤json.dumps
函数的时候,需要将dumps的default参数设置为转化函数:
import json as js
class MyObj(object):
def__init__(self, s):
self.s = s
def__repr__(self):
return'<MyObj(%s)>' % self.s
obj = MyObj(12)
try:
print js.dumps(obj)
except TypeError, err:
print err
def convert_to_builtin_type(obj):
print'default(', repr(obj), ')'
d = {'__class__': obj.__class__.__name__,
'__module__': obj.__module__,
}
d.update(obj.__dict__)
return d
print js.dumps(obj, default=convert_to_builtin_type)
#Output
<MyObj(12)> is not JSON serializable
default( <MyObj(12)> )
{"s": 12, "__module__": "__main__", "__class__": "MyObj"}
相反,如果要把json decode 成python对象,同样也需要⾃定转换函数,传递给json.loads⽅法的object_hook参数:
def dict_to_object(d):
if'__class__'in d:
class_name = d.pop('__class__')
module_name = d.pop('__module__')
module = __import__(module_name)
print "MODULE:", module
class_ = getattr(module, class_name)
print "CLASS", class_
args = dict((de('ascii'), value) for key, value in d.items())
print 'INSTANCE ARGS:', args
inst = class_(**args)
else:
inst = d
return inst
encoded_object = '[{"s":"helloworld","__module__":"__main__","__class__":"MyObj"}]'
myobj_instance = js.loads(encoded_object, object_hook=dict_to_object)
print myobj_instance
#Output
MODULE: <module '__main__' from 'jsonIO.py'>
CLASS <class '__main__.MyObj'>
INSTANCE ARGS: {'s': u'helloworld'}
[<MyObj(helloworld)>]
对json⽂件进⾏读写

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。