Python JSON数据解析、操作集合

  JSON格式是网站和API使用的通用标准格式,现在主流的一些数据库(如PostgreSQL)都支持JSON格式。在本文中,我们将介绍如何使用Python处理JSON数据。首先,让我们先来看看JSON的定义。

相关模块

  • 内置模块:json

  • 强大的解析模块:demjson
  • 强大的查询模块:jsonpath

定义

JSON或JavaScript Object Notation,是一种使用文本存储数据对象的格式。换句话说,它是一种数据结构,将对象用文本形式表示出来。尽管它来源自JavaScript,但它已成为传输对象的实际标准。

{
   "name": "United States",
   "population": 23123124,
   "capital": "dasdasd",
   "languages": [
  "English",
  "Spanish"
   ]
}

在这个例子中,JSON数据看起来像一个Python字典。像字典一样,JSON以键值对的形式传递数据。

然而,JSON数据也可以是字符串、数字、布尔值或列表。

 

 

一、内置模块 json

img

  • json.dumps(): 对数据进行编码。

  • json.loads(): 对数据进行解码。

使用方法

# Python 字典类型转换为 JSON 对象
data = {
    'no' : 1,
    'name' : [1,2,3,4],
}
 
json_str = json.dumps(data)
​
# 将 JSON 对象转换为 Python 字典
data2 = json.loads(json_str)

 

1.1 将JSON字符串转换为Python类对象

类(class)对象不是JSON序列化对象。

import json
​
​
class People(object):
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
​
​
people_obj = People("张三", 32, "")
​
print(json.dumps(people_obj))
# TypeError: Object of type People is not JSON serializable
# 类型错误:People对象不可以JSON序列化

解决方案

要将对象转换为JSON,我们需要编写一个扩展JSONEncoder的新类。在这个类中,需要实现default()。此方法将具有返回JSON的自定义代码。

class PeopleEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, People):
            # 处理People的序列化
            return {
                "name": obj.name,
                "age": obj.age,
                "gender": obj.gender,
            }
        else:
            # 使用父类的序列化方法
            super(PeopleEncoder, self).default(obj)
# 使用
print(json.dumps(people_obj, cls=PeopleEncoder, ensure_ascii=False))
# {"name": "张三", "age": 32, "gender": "男"}

1.2 从JSON对象创建Python类对象 -- object_hook

使用object_hook

class People(object):
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
​
    @staticmethod
    def object_hook(d):
        return People(**d)
​
​
people_obj = People("张三", 32, "")
json_str = '{"name": "张三", "age": 32, "gender": "男"}'
​
p = json.loads(json_str, object_hook=People.object_hook)
print(type(p))  # <class '__main__.People'>
print(p.name, p.age, p.gender)  # 张三 32 男

二、demjson 解决多种疑难杂症

Demjson是 python 的第三方模块库,可用于编码和解码 JSON 数据,包含了 JSONLint 的格式化及校验功能。

安装

pip install demjson

使用

  • demjson.encode: 将 Python 对象编码成 JSON 字符串

  • demjson.decode: 将已编码的JSON 字符串解码为 Python 对象

该包功能相较于json而言具有格式化校验功能,支持js的多种格式的对象转字典

# 可以解析包含 ' 的字符串
d_s = """{"a":1, "b":2, 'c':3}"""
d = demjson.decode(d_s)
​
# 解析js的的特殊字符
js_obj = """{a:1,b:2}"""
d2 = demjson.decode(js_obj)
​
# 包含不规范的js字符串 undefined、null
js_obj2 = '''{a:undefined,b:null}'''
d3 = demjson.decode(js_obj)

三、jsonpath 快速处理dict的深度查询

  • JSONPath - 用于JSON的XPath

  • 用来解析多层嵌套的json数据;JsonPath 是一种信息抽取类库,是从JSON文档中抽取指定信息的工具.

官方文档:http://goessner.net/articles/JsonPath

安装

pip install jsonpath

强大之处

import jsonpath
res=jsonpath.jsonpath(dic_name,'$..key_name') # 查询字典中所有的key_name的值,返回列表

嵌套n层也能取到所有key_name信息,其中:“$”表示最外层的{},“..”表示模糊匹配,当传入不存在的key_name时,程序会返回false.

使用规则

  • jsonpath表达式使用注释
$.store.book[0].title 
  • 括号 -注释

$['store']['book'][0]['title']

jsonpath与xpath的联系

JSONPath语法元素与XPath对应的完整概述和并排比较。

XpathJSONPath描述
/ $ 跟节点
. @ 现行节点
/ . or [] 取子节点
.. n/a 就是不管位置,选择所有符合条件的条件
* * 匹配所有元素节点
[] [] 迭代器标示(可以在里面做简单的迭代操作,如数组下标,根据内容选值等)
&#124 [,] 支持迭代器中做多选
[] ?() 支持过滤操作
n/a () 支持表达式计算
() n/a 分组,JsonPath不支持

实例演示

{ "store": {
    "book": [ 
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

jsonpath与xpath写法及其含义,帮助理解

XPath的JSONPath结果
/store/book/author $.store.book[*].author 商店里所有书籍的作者
//author $..author 所有作者
/store/* $.store.* 商店里的所有东西,都是一些书和一辆红色的自行车。
/store//price $.store..price 商店里一切的价格。
//book[3] $..book[2] 第三本书
//book[last()] $..book[(@.length-1)] $..book[-1:] 最后一本书。
//book[position()<3] $..book[0,1] $..book[:2] 前两本书
//book[isbn] $..book[?(@.isbn)] 使用isbn number过滤所有书籍
//book[price<10] $..book[?(@.price<10)] 过滤所有便宜10以上的书籍
//* $..* XML文档中的所有元素。JSON结构的所有成员。

python使用示例

jsonpath.jsonpath(匹配的字典,'jsonpath表达式')
 
如:res2= jsonpath.jsonpath(d,'$..name')  #找d字典下面所有的name对应的值,返回一个列表

完整例子

shop={
    "store": {
        "book": [
            {
                "category": "reference",
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "price": 8.95
            },
            {
                "category": "fiction",
                "author": "Evelyn Waugh",
                "title": "Sword of Honour",
                "price": 12.99
            },
            {
                "category": "fiction",
                "author": "Herman Melville",
                "title": "Moby Dick",
                "isbn": "0-553-21311-3",
                "price": 8.99
            },
            {
                "category": "fiction",
                "author": "J. R. R. Tolkien",
                "title": "The Lord of the Rings",
                "isbn": "0-395-19395-8",
                "price": 22.99
            }
        ],
        "bicycle": {
            "color": "red",
            "price": 19.95
        }
    },
    "expensive": 10
}
​
import jsonpath
#商店里所有书籍的作者
author_list=jsonpath.jsonpath(shop,'$.store.book[*].author')
print(author_list) #['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien']
#返回所有的作者
author_list2=jsonpath.jsonpath(shop,'$..author')
print(author_list2) #['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J
#商店里的所有东西
category_dx=jsonpath.jsonpath(shop,'$.store.*')
print(category_dx)
​
#商店里一切的价格
store_price_list=jsonpath.jsonpath(shop,'$.store..price')
print(store_price_list) #[8.95, 12.99, 8.99, 22.99, 19.95]
#第三本书
book_3=jsonpath.jsonpath(shop,'$..book[2]')
print(book_3)
​
#最后一本书
num=len(jsonpath.jsonpath(shop,'$..book'))-1
book_last=jsonpath.jsonpath(shop,f'$..book[{num}]')
print(book_last)
​
#前两本书
book_12=jsonpath.jsonpath(shop,f'$..book[0,1]')
print(book_12)
​
#过滤所有便宜10以上的书籍
book_lg10=jsonpath.jsonpath(shop,'$..book[?(@.price<10)]')
print(book_lg10)
​
#使用isbn number过滤所有书籍
book_lg10=jsonpath.jsonpath(shop,'$..book[?(@.isbn)]')
print(book_lg10)  

 

posted @ 2022-08-20 15:57  柳帅  阅读(1720)  评论(0编辑  收藏  举报
//替换成自己路径的js文件