一、jsonpath

 

1. jsonpath介绍

用来解析多层嵌套的 json 数据;JsonPath 是一种信息抽取类库,是从 JSON 文档中抽取指定信息的工具,提供多种语言实现版本,包括:Javascript, Python, PHP 和 Java。

使用方法:

  1.  
    import jsonpath
  2.  
     
  3.  
     
  4.  
    res=jsonpath.jsonpath(dic_name,’$..key_name’)
  5.  
    # 嵌套 n 层也能取到所有 key_name 信息,
  6.  
    # 其中:“$”表示最外层的{},
  7.  
    # “..”表示模糊匹配,当传入不存在的 key_name时,程序会返回false

 

2. JsonPath 对于 JSON 来说,相当于 XPath 对于 XML

jsonpath 安装:pip install jsonpath
官方文档:http://goessner.net/articles/JsonPath

jsonpath-rw:JSONPath 的一个健壮且显著扩展的Python实现,带有一个明确的AST用于元编程。
jsonpath-rw 介绍:https://pypi.org/project/jsonpath-rw/
jsonpath-rw 安装:pip install jsonpath-rw

 

3. JsonPath 与 XPath 语法对比:

Json 结构清晰,可读性高,复杂度低,非常容易匹配,下表中对应了XPath 的用法。

对比:

Python 使用示例:

  1.  
    # 使用格式: jsonpath.jsonpath(匹配的字典,’jsonpath表达式’)
  2.  
     
  3.  
    # 找 d字典下面所有的name对应的值,返回一个列表
  4.  
    res2 = jsonpath.jsonpath(d,’$..name’)

示例:

  1.  
    import jsonpath
  2.  
     
  3.  
     
  4.  
    def learn_json_path():
  5.  
    book_store = {
  6.  
    “store”: {
  7.  
    “book”: [
  8.  
    {
  9.  
    “category”: “reference”,
  10.  
    “author”: “Nigel Rees”,
  11.  
    “title”: “Sayings of the Century”,
  12.  
    “price”: 8.95
  13.  
    },
  14.  
    {
  15.  
    “category”: “fiction”,
  16.  
    “author”: “Evelyn Waugh”,
  17.  
    “title”: “Sword of Honour”,
  18.  
    “price”: 12.99
  19.  
    },
  20.  
    {
  21.  
    “category”: “fiction”,
  22.  
    “author”: “Herman Melville”,
  23.  
    “title”: “Moby Dick”,
  24.  
    “isbn”: “0-553-21311-3”,
  25.  
    “price”: 8.99
  26.  
    },
  27.  
    {
  28.  
    “category”: “fiction”,
  29.  
    “author”: “J. R. R. Tolkien”,
  30.  
    “title”: “The Lord of the Rings”,
  31.  
    “isbn”: “0-395-19395-8”,
  32.  
    “price”: 22.99
  33.  
    }
  34.  
    ],
  35.  
    “bicycle”: {
  36.  
    “color”: “red”,
  37.  
    “price”: 19.95
  38.  
    }
  39.  
    },
  40.  
    “expensive”: 10
  41.  
    }
  42.  
    # print(type(book_store))
  43.  
     
  44.  
    # 查询store下的所有元素
  45.  
    print(jsonpath.jsonpath(book_store, ‘$.store.*’))
  46.  
     
  47.  
    # 获取json中store下book下的所有author值
  48.  
    print(jsonpath.jsonpath(book_store, ‘$.store.book[*].author’))
  49.  
     
  50.  
    # 获取所有json中所有author的值
  51.  
    print(jsonpath.jsonpath(book_store, ‘$..author’))
  52.  
     
  53.  
    # 获取json中store下所有price的值
  54.  
    print(jsonpath.jsonpath(book_store, ‘$.store..price’))
  55.  
     
  56.  
    # 获取json中book数组的第3个值
  57.  
    print(jsonpath.jsonpath(book_store, ‘$.store.book[2]’))
  58.  
     
  59.  
    # 获取所有书
  60.  
    print(jsonpath.jsonpath(book_store, ‘$..book[0:1]’))
  61.  
     
  62.  
    # 获取json中book数组中包含isbn的所有值
  63.  
    print(jsonpath.jsonpath(book_store, ‘$..book[?(@.isbn)]’))
  64.  
     
  65.  
    # 获取json中book数组中price<10的所有值
  66.  
    print(jsonpath.jsonpath(book_store, ‘$..book[?(@.price<10)]’))
  67.  
     
  68.  
     
  69.  
    if __name__ == ‘__main__’:
  70.  
    learn_json_path()
  71.  
     

 

4. 使用实例

示例代码 1:

  1.  
    d={
  2.  
    “error_code”: 0,
  3.  
    “stu_info”: [
  4.  
    {
  5.  
    “id”: 2059,
  6.  
    “name”: “小白”,
  7.  
    “sex”: “男”,
  8.  
    “age”: 28,
  9.  
    “addr”: “河南省济源市北海大道32号”,
  10.  
    “grade”: “天蝎座”,
  11.  
    “phone”: “18378309272”,
  12.  
    “gold”: 10896,
  13.  
    “info”:{
  14.  
    “card”:434345432,
  15.  
    “bank_name”:’中国银行’
  16.  
    }
  17.  
     
  18.  
    },
  19.  
    {
  20.  
    “id”: 2067,
  21.  
    “name”: “小黑”,
  22.  
    “sex”: “男”,
  23.  
    “age”: 28,
  24.  
    “addr”: “河南省济源市北海大道32号”,
  25.  
    “grade”: “天蝎座”,
  26.  
    “phone”: “12345678915”,
  27.  
    “gold”: 100
  28.  
    }
  29.  
    ]
  30.  
    }
  31.  
     
  32.  
    res= d[“stu_info”][1][‘name’] #取某个学生姓名的原始方法:通过查找字典中的key以及list方法中的下标索引
  33.  
    print(res) #输出结果是:小黑
  34.  
     
  35.  
    import jsonpath
  36.  
    res1=jsonpath.jsonpath(d,’$..name’) #嵌套n层也能取到所有学生姓名信息,$表示最外层的{},..表示模糊匹配
  37.  
    print(res1) #输出结果是list:[‘小白’, ‘小黑’]
  38.  
     
  39.  
    res2= jsonpath.jsonpath(d,’$..bank_name’)
  40.  
    print(res2) #输出结果是list:[‘中国银行’]
  41.  
     
  42.  
    res3=jsonpath.jsonpath(d,’$..name123′) #当传入不存在的key(name)时,返回False
  43.  
    print(res3) #输出结果是:False

示例代码 2:

以拉勾网城市 JSON 文件 http://www.lagou.com/lbs/getAllCitySearchLabels.json 为例,获取所有城市。

  1.  
    import json
  2.  
    import jsonpath
  3.  
    import requests
  4.  
     
  5.  
    url = ‘http://www.lagou.com/lbs/getAllCitySearchLabels.json’
  6.  
     
  7.  
    custom_headers = {
  8.  
    “Accept”: “*/*”,
  9.  
    “Accept-Encoding”: “gzip, deflate, br”,
  10.  
    “Accept-Language”: “zh-CN,zh;q=0.9”,
  11.  
    “Cache-Control”: “max-age=0”,
  12.  
    “Connection”: “keep-alive”,
  13.  
    “Host”: “www.lagou.com”,
  14.  
    “User-Agent”: “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 “
  15.  
    “(KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36”
  16.  
    }
  17.  
     
  18.  
    response = requests.get(url, headers=custom_headers)
  19.  
    json_obj = json.loads(response.text)
  20.  
    print(json_obj)
  21.  
     
  22.  
    # 从根节点开始,匹配name节点
  23.  
    city_list = jsonpath.jsonpath(json_obj, ‘$..name’)
  24.  
    print(city_list)
  25.  
    print(type(city_list))
  26.  
     
  27.  
    # A 下面的节点
  28.  
    jp = jsonpath.jsonpath(json_obj, ‘$..A.*’)
  29.  
    print(jp)
  30.  
     
  31.  
    # A 下面节点的name
  32.  
    jp = jsonpath.jsonpath(json_obj, ‘$..A.*.name’)
  33.  
    print(jp)
  34.  
     
  35.  
    # C 下面节点的name
  36.  
    jp = jsonpath.jsonpath(json_obj, ‘$..C..name’)
  37.  
    print(jp)
  38.  
     
  39.  
    # C 下面节点的第二个
  40.  
    jp = jsonpath.jsonpath(json_obj, ‘$..C[1]’)
  41.  
    print(jp)
  42.  
     
  43.  
    # C 下面节点的第二个的name
  44.  
    jp = jsonpath.jsonpath(json_obj, ‘$..C[1].name’)
  45.  
    print(jp)
  46.  
     
  47.  
    # C 下面节点的2到5的name
  48.  
    jp = jsonpath.jsonpath(json_obj, ‘$..C[1:5].name’)
  49.  
    print(jp)
  50.  
     
  51.  
    # C 下面节点最后一个的name
  52.  
    jp = jsonpath.jsonpath(json_obj, ‘$..C[(@.length-1)].name’)
  53.  
    print(jp)
  54.  
     
  55.  
    with open(‘city.json’, ‘w’, encoding=’utf-8′) as f:
  56.  
    content = json.dumps(city_list, ensure_ascii=False, indent=4)
  57.  
    print(content)
  58.  
    f.write(content)

注意事项:

json.loads() 是把 Json 格式字符串解码转换成 Python 对象,如果在 json.loads 的时候出错,要注意被解码的 Json 字符的编码。
如果传入的字符串的编码不是 UTF-8 的话,需要制定字符编码的参数:encoding

dataDict = json.loads(jsonStrGBK);

dataJsonStr 是 JSON 字符串,假设其编码本身是非 UTF-8 的话而是 GBK 的,那么上述代码会导致出错,改为对应的。

dataDict = json.loads(jsonStrGBK, encoding="GBK")

如果 dataJsonStr 通过 encoding 指定了合适的编码,但是其中又包含了其它编码的字符,则需要先去将 dataJsonStr 转换为Unicode,然后再指定编码格式调用 json.loads()

  1.  
    dataJsonStrUni = data.JsonStr.decode(“GB2312”)
  2.  
    dataDict = json.loads(dataJsontrUni, encoding=”GB2312″)

 

字符串编码转换

其实编码问题很好搞定,只要记住一点:任何平台的任何编码,都能和Unicode互相转换。UTF-8 与 GBK 互相转换,那就先把 UTF-8 转换成 Unicode,再从 Unicode 转换成 GBK,反之同理。

  1.  
    # 这是一个 UTF-8 编码的字符串
  2.  
    utf8Str = “你好地球”
  3.  
     
  4.  
    # 1. 将 UTF-8 编码的字符串 转换成 Unicode 编码
  5.  
    unicodeStr = utf8Str.decode(“UTF-8”)
  6.  
     
  7.  
    # 2. 再将 Unicode 编码格式字符串 转换成 GBK 编码
  8.  
    gbkData = unicodeStr.encode(“GBK”)
  9.  
     
  10.  
    # 1. 再将 GBK 编码格式字符串 转化成 Unicode
  11.  
    unicodeStr = gbkData.decode(“gbk”)
  12.  
     
  13.  
    # 2. 再将 Unicode 编码格式字符串转换成 UTF-8
  14.  
    utf8Str = unicodeStr.encode(“UTF-8”)
  • decode: 的作用是将其它编码的字符串转换成 Unicode 编码
  • encode :的作用是将 Unicode 编码转换成其他编码的字符串
  • 一句话:UTF-8 是对 Unicode 字符集记性编码的一种编码格式

 

 

二、Python 序列化之 json、pickle、msgpack 之 dumps、loads 区别于用法

 

Python 之 Json 模块

json 类型特征

  • json 是一种通用的数据类型,一般情况下接口返回的数据类型都是json
  • 长得像 Python 字典,形式也是 k-v
  • 其实 json 是字符串
  • 字符串不能用 key、value 来取值,所以要先转换为 Python 的字典才可以

示例:

  1.  
    import json
  2.  
     
  3.  
    test_str = ”’
  4.  
    {
  5.  
    “noticeLoginFlag”: “1”,
  6.  
    “ticket_id”: “gh_45679b88e7a”,
  7.  
    “pgv_si”: “s29623456176”,
  8.  
    “pgv_pvi”: “1328457192”
  9.  
    }
  10.  
    ”’
  11.  
     
  12.  
    data_dict = json.loads(test_str)
  13.  
    print(data_dict) # 打印字典
  14.  
    print(type(data_dict)) # 打印 data_dict 类型
  15.  
    print(list(data_dict.keys())) # 打印字典的所有key
  16.  
     
  17.  
    data_string = json.dumps(data_dict, indent=4, ensure_ascii=False)
  18.  
    print(type(data_string))
  19.  
    print(data_string)

 

Python 之 simplejson 模块

simplejson 更轻量级,使用方法完全与 json 相同

 

Python 之 pickle 模块

pickle 类型特征

  • pickle 模块用于实现 序列化 和 反序列化。
  • 序列化 dumps 可以将 list、dict 等数据结构转化为二进制
  • 反序列化 loads 可以将字符串转化为 list、dict

数据结构(可以是列表、字典等)转成字符串:dumps()方法:将一个数据结构编码为二进制数据

  1.  
    import pickle
  2.  
     
  3.  
    data_dict = {‘name’: ‘king’, ‘age’: ‘100’}
  4.  
    data_dict_list = [
  5.  
    {‘name’: ‘king’, ‘age’: ‘100’},
  6.  
    {‘name’: ‘king’, ‘age’: ‘100’}
  7.  
    ]
  8.  
     
  9.  
    data_string_1 = pickle.dumps(data_dict)
  10.  
    print(type(data_string_1))
  11.  
    print(data_string_1)
  12.  
     
  13.  
    data_string_2 = pickle.dumps(data_dict)
  14.  
    print(type(data_string_2))
  15.  
    print(data_string_2)
  16.  
     
  17.  
    temp = pickle.loads(data_string_2)
  18.  
    print(type(temp))
  19.  
    print(temp)

 

Python 之 msgpack 模块

安装 msgpack :pip install msgpack

msgpack 类型特征

  • msgpack 是一种有效的二进制序列化格式。它使您可以在多种语言(如JSON)之间交换数据。但是它更快,更小。
  • 序列化 packb 可以将 list、dict 等数据结构转化为二进制 ( packb 别名为 dumps )
  • 反序列化 loads 可以将字符串转化为 list、dict ( unpackb 别名为 loads )
  1.  
    import msgpack
  2.  
     
  3.  
    data_dict = {‘name’: ‘king’, ‘age’: ‘100’}
  4.  
    data_dict_list = [
  5.  
    {‘name’: ‘king’, ‘age’: ‘100’},
  6.  
    {‘name’: ‘king’, ‘age’: ‘100’}
  7.  
    ]
  8.  
     
  9.  
    data_string_1 = msgpack.dumps(data_dict, use_bin_type=True)
  10.  
    print(type(data_string_1))
  11.  
    print(data_string_1)
  12.  
     
  13.  
    temp_1 = msgpack.loads(data_string_1, use_list=False)
  14.  
    print(temp_1)
  15.  
     
  16.  
    data_string_2 = msgpack.dumps(data_dict_list)
  17.  
    print(type(data_string_2))
  18.  
    print(data_string_2)
  19.  
     

示例:

  1.  
    import datetime
  2.  
    import msgpack
  3.  
     
  4.  
    useful_dict = {
  5.  
    “id”: 1,
  6.  
    “created”: datetime.datetime.now(),
  7.  
    }
  8.  
     
  9.  
     
  10.  
    def decode_datetime(obj):
  11.  
    if b’__datetime__’ in obj:
  12.  
    obj = datetime.datetime.strptime(obj[“as_str”], “%Y%m%dT%H:%M:%S.%f”)
  13.  
    return obj
  14.  
     
  15.  
     
  16.  
    def encode_datetime(obj):
  17.  
    if isinstance(obj, datetime.datetime):
  18.  
    return {‘__datetime__’: True, ‘as_str’: obj.strftime(“%Y%m%dT%H:%M:%S.%f”)}
  19.  
    return obj
  20.  
     
  21.  
     
  22.  
    packed_dict = msgpack.packb(useful_dict, default=encode_datetime, use_bin_type=True)
  23.  
    this_dict_again = msgpack.unpackb(packed_dict, object_hook=decode_datetime, raw=False)
  24.  
     
  25.  
    print(packed_dict)
  26.  
    print(this_dict_again)

 

 

 
 
版权声明:本文为tandoori原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/tandoori/p/16304685.html