Python处理json文件如何获取JSON数据的类型信息

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

用Python来处理JSON数据的场景非常多,一般是加载完JSON数据后,通过字典的方式直接去访问JSON字段。如果只是临时性的几行代码,用完就扔,那也没什么,怎么简单怎么来。但如果是需要维护的代码,或者多人协作的代码,那代码还是得写得优雅一点,毕竟team["members"][0]["age"]这样的代码没有team.members[0].age读起来那么优雅,而且没有错误检查,更别说后者还有类型提示这样的好处了。

我们来分别看看这两种处理方式,和适用的场景。


一、通过字典的方式访问JSON数据

假设有以下JSON数据要处理:

文件名:team.json

{
    "name": "村BA",
    "members": [
        {
            "name": "张三",
            "age": 20
        },
        {
            "name": "李四",
            "age": 19
        },
    ]
}

Python加载JSON数据:

import json

team = json.loads(open("team.json").read())

加载完返回字典类型team,然后通过team["name"]team["members"][0]["age"]这样的方式去访问JSON字段。

这就是传统做法,简单快速,但因为没有类型信息,代码编辑器没办法辅助提示,也不会检查错误(例如,team["members"]写成了team["member"]),换言之,错误可能要到运行时才会被发现。另外,代码也不够优雅。
这也是Python在v3.5之前存在的问题,直到3.5开始引入类型信息(借鉴了Typescript)。

二、通过数据类的方式访问JSON数据

相较之下,如果通过数据类的方式去处理,则可以获得以上的种种好处,类型提示,减少运行时错误,更优雅的代码风格。我们来看看怎么做。

2.1 定义数据类

@dataclass装饰器来装饰我们的数据类:

from dataclasses import dataclass
from typing import List

@dataclass
class People:
	name: str
	age: int

@dataclass
class Team:
	name: str
	members: List[People]

2.2 加载数据

像之前一样,加载JSON数据:

team: Team = json.loads(open('team.json').read())

这时如果访问team.name会提示'dict' object has no attribute 'members'错误,尽管我们为team标注了类型信息Team,但说到底team还是一个dict数据,Python并不会根据标注的类型强制转换,这些手动标注的类型信息是面向用户和代码编辑器,不是面向运行时的。这一点跟Typescript是一样的,在生成Javascript代码后Typescript的类型信息就没了,不会带到运行时。

解决的方案是在加载的时候增加一个object_hook

team: Team = json.loads(open('team.json').read(), object_hook=lambda d: SimpleNamespace(**d))

这个解决方案跟@dataclass本身并没有关系,换言之,不用@dataclass装饰数据类也可以,但@dataclass有一些好处:

@dataclass用于自动为类生成特殊方法,例如 init()、repr()、eq() 等。这使得创建数据类(通常用于存储数据的类)变得更加简单和直观。
使用 @dataclass 装饰器的主要优点包括:
减少样板代码:它自动生成初始化方法、字符串表示方法和相等性比较方法,减少了手动编写这些方法的需要。
可读性:自动生成的方法遵循一致的命名和行为模式,使得代码更加易读和易于维护。
简洁性:使用 @dataclass 可以使代码更加简洁,减少重复代码。
例如:可以直接定义一个对象:

person = People("王五", 21)

如果没有@dataclass定义,那就必须为People定义一个初始化函数:

def __init__(self, name, age):
    self.name = name
    self.age = age

现在代码编辑器就可以给你类型辅助信息了,有错误也会提示(例如,team.members写成了team.member立刻报错)。需要维护的代码或多人协助的项目,前期多做一些工作,可以大大减少运行时的错误和维护成本。


总结

两种方法各有利弊,取决于要处理的场景。传统的方式简单快速,适合用完即扔。数据类的方式可以在编写代码时获取编辑器提示,减少运行时错误,但要先对数据进行类型标注,适合需要长期维护和多人协作的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值