如何将Pexels API的requests响应JSON转为Python类对象
问题原因
你直接通过SearchResponse(**data)初始化响应对象时,仅顶层字段会被赋值为基础类型值,嵌套的字典(如src字段)、字典列表(如photos字段)仍然是原生Python dict/list类型,自然无法通过属性方式访问内部字段。另外注意Python列表索引从0开始,第一个元素是photos[0]而非photos[1]。
实现方案
两种常用实现方式,按需选择即可:
方案1:标准库dataclass(零依赖)
使用Python 3.7+内置的dataclass,通过__post_init__方法手动处理嵌套对象转换,不需要安装第三方依赖。
首先编写你的types.py:
from dataclasses import dataclass from typing import List, Optional # 最内层的图片尺寸链接类 @dataclass class PhotoSrc: original: str large2x: str large: str medium: str small: str portrait: str landscape: str tiny: str # 单张图片类 @dataclass class Photo: id: int width: int height: int url: str photographer: str photographer_url: str photographer_id: int avg_color: str src: PhotoSrc liked: bool alt: str # 搜索结果顶层响应类 @dataclass class SearchResponse: total_results: int page: int per_page: int photos: List[Photo] next_page: Optional[str] = None def __post_init__(self): # 初始化后自动转换嵌套的列表和字典为对应类实例 self.photos = [ Photo( **item, src=PhotoSrc(**item["src"]) ) for item in self.photos ]
你现有的search_photos方法不需要修改,直接返回SearchResponse(**data)即可实现属性访问。
方案2:Pydantic(自动转换,适合复杂接口)
如果接口嵌套层级深、字段多,推荐使用Pydantic库,它会自动递归完成所有嵌套结构的类型转换和校验,不需要手动写转换逻辑,非常适合写API封装。
- 先安装依赖:
pip install pydantic
- 编写
types.py:
from pydantic import BaseModel from typing import List, Optional class PhotoSrc(BaseModel): original: str large2x: str large: str medium: str small: str portrait: str landscape: str tiny: str class Photo(BaseModel): id: int width: int height: int url: str photographer: str photographer_url: str photographer_id: int avg_color: str src: PhotoSrc liked: bool alt: str class SearchResponse(BaseModel): total_results: int page: int per_page: int photos: List[Photo] next_page: Optional[str] = None
- 修改
search_photos里的返回逻辑,用Pydantic的模型校验方法加载数据:
def search_photos( self, query: str, orientation: str = "", size:str = "", color: str = "", locale: str = "", page: int = 1, per_page: int = 15, **kwargs ) -> SearchResponse: # 用requests的params参数自动处理url编码,避免特殊字符请求错误 params = {k:v for k,v in { "query": query, "orientation": orientation, "size": size, "color": color, "locale": locale, "page": page, "per_page": per_page }.items() if v} data, req = self._make_request("search", params=params) # pydantic v2用model_validate,v1版本替换为parse_obj即可 return SearchResponse.model_validate(data)
使用效果
两种方案实现后,都可以流畅通过属性访问任意层级字段:
resp = client.search_photos("nature") print(resp.total_results) # 输出总结果数 print(resp.photos[0].alt) # 输出第一张图片的alt文本 print(resp.photos[0].src.original) # 输出第一张图片的原图链接 print(resp.next_page) # 输出下一页地址
额外提示:你当前直接拼接query字符串的写法存在隐患,遇到查询词包含空格、&等特殊字符时会出现请求错误,建议统一通过requests的
params参数传递URL查询参数,会自动完成URL编码。
内容的提问来源于stack exchange,提问作者Joker Hacker
相关产品推荐
相关产品推荐

