python解析json文件
(转载)http://blog.csdn.net/dyx404514/article/details/50186413
最近项目数据用的是json格式,学习了一下Python解析json格式的方式,总结一下备忘。
文章参考链接:
http://liuzhijun.iteye.com/blog/1859857
http://www.cnblogs.com/coser/archive/2011/12/14/2287739.html
首先简单了解一下什么是json格式:
JSON(JavaScript Object Notation):一种轻量级数据交换格式,相对于XML而言更简单,也易于阅读和编写,机器也方便解析和生成,Json是javascript中的一个子集。
JSON建构于两种结构:
“名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。
这些都是常见的数据结构。事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式在同样基于这些结构的编程语言之间交换成为可能。
json的官方文档见: http://json.org
下面是json格式的简单例子(来自百度百科):
按照最简单的形式,可以用下面这样的 JSON 表示”名称 / 值对”:
{"firstName":"Brett"}
- 1
- 1
这个示例非常基本,而且实际上比等效的纯文本”名称 / 值对”占用更多的空间:
但是,当将多个”名称 / 值对”串在一起时,JSON 就会体现出它的价值了。首先,可以创建包含多个”名称 / 值对”的 记录,比如:
{"firstName":"Brett","lastName":"McLaughlin","email":"aaaa"}
- 1
- 1
从语法方面来看,这与”名称 / 值对”相比并没有很大的优势,但是在这种情况下 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"}
]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
这不难理解。在这个示例中,只有一个名为 people的变量,值是包含三个条目的数组,每个条目是一个人的记录,其中包含名、姓和电子邮件地址。上面的示例演示如何用括号将记录组合成一个值。当然,可以使用相同的语法表示多个值(每个值包含多个记录):
{
"programmers": [{
"firstName": "Brett",
"lastName": "McLaughlin",
"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"
}]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
这里最值得注意的是,能够表示多个值,每个值进而包含多个值。但是还应该注意,在不同的主条目(programmers、authors 和 musicians)之间,记录中实际的名称 / 值对可以不一样。JSON 是完全动态的,允许在 JSON 结构的中间改变表示数据的方式。
在处理 JSON 格式的数据时,没有需要遵守的预定义的约束。所以,在同样的数据结构中,可以改变表示数据的方式,甚至可以以不同方式表示同一事物。
表示object
{
"name":"test",
"type":{
"name":"seq",
"parameter":["1","2"]
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
其中type属性是一个object,也就是属性嵌套。
以上是json格式的简单介绍,下面就总结写python解析json格式和文件的方法。
Python操作json的标准api库参考:http://docs.python.org/library/json.html
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]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
我们可以看到得到的输出原数据和类似,但是还是有些细微的不同,例如上例中的元组则转换为了列表。在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'>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
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", default=None, sort_keys=False, **kw)
- 1
- 1
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]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
以上都是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"}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
相反,如果要把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((key.encode('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)>]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
对json文件进行读写
以上例子都是在代码中直接定义python类型和json字符串,下面介绍如何对json文件进行读写并进行编码解码。
前面已经提到,json模块中对文件操作的函数分别为 json.load()和json.dump(),他们操作都和dumps和loads类似,下面举两个小例子,分别对应解码和编码。
1) 读取json文件并进行解码。
假设文件 ‘my.json’中的内容为:
#my.json
{
"name":"test",
"type":{
"name":"seq",
"parameter":["1","2"]
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
下面的代码读取‘my.json’文件并进行解码:
import json as js
f = file('my.json')
print js.load(f)
#Output
{u'type': {u'parameter': [u'1', u'2'], u'name': u'seq'}, u'name': u'test'}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
2)对python类型进行编码并写入文件
编码也基本类似,不多说了,直接上代码:
import json as js
out = file('output.json', 'w+')
obj = [{'aa': 1, 'bb': 2, 'cc': 3},
(1, 2, 3, 4), 'hello world', 0.5, 100, None, True]
js.dump(obj, out, indent=4)
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
程序运行完之后可以看到 output.json文件中的内容为:
[
{
"aa": 1,
"cc": 3,
"bb": 2
},
[
1,
2,
3,
4
],
"hello world",
0.5,
100,
null,
true
]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
python对json的解析总结就到这里。
以上
上一篇: linux shell中“.” 和 “./”执行的区别详解
下一篇: Python解析Json文件