将请求响应json转换为Python类对象

发布于 2025-02-10 15:24:21 字数 3252 浏览 1 评论 0原文

嗨,我正在为pexels API写一个Python API包装器, 我的API响应如下:

{
  "total_results": 10000,
  "page": 1,
  "per_page": 1,
  "photos": [
    {
      "id": 3573351,
      "width": 3066,
      "height": 3968,
      "url": "https://www.pexels.com/photo/trees-during-day-3573351/",
      "photographer": "Lukas Rodriguez",
      "photographer_url": "https://www.pexels.com/@lukas-rodriguez-1845331",
      "photographer_id": 1845331,
      "avg_color": "#374824",
      "src": {
        "original": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png",
        "large2x": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
        "large": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&h=650&w=940",
        "medium": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&h=350",
        "small": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&h=130",
        "portrait": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800",
        "landscape": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200",
        "tiny": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=200&w=280"
      },
      "liked": false,
      "alt": "Brown Rocks During Golden Hour"
    }
  ],
  "next_page": "https://api.pexels.com/v1/search/?page=2&per_page=1&query=nature"
}

我希望响应中的每件事都可以作为类对象访问,因此尝试制作单独的自定义对象,我的 type.py

但是我无法访问诸如photos 1 .alt

。功能:

    def _make_request(
            self,
            path: str,
            method: str = "get",
            **kwargs: Dict[Any, Any]
        ) -> Tuple[Union[Dict, str], requests.Response]:
    
            header = {'Authorization': self._token}
            req = self.session.request(method, f'{self._host}/{path}', headers=header,**kwargs)
    
            if req.status_code in [200, 201]:
                try:
                    return req.json(), req
                except JSONDecodeError:
                    return req.text, req
            elif req.status_code == 400:
                raise PexelsError("Bad Request Caught")
            else:
                raise PexelsError(f"{req.status_code} : {req.reason}")
    
        def search_photos(
            self, 
            query: str, 
            orientation: str = "", 
            size:str = "",
            color: str = "",
            locale: str = "",
            page: int = 1,
            per_page: int = 15,
            **kwargs
        ) -> SearchResponse:
    
            data, req = self._make_request(f"search?query={query}")
            return SearchResponse(**data)

Hi i'm writing a python API wrapper for Pexels API,
I have API response as follow:

{
  "total_results": 10000,
  "page": 1,
  "per_page": 1,
  "photos": [
    {
      "id": 3573351,
      "width": 3066,
      "height": 3968,
      "url": "https://www.pexels.com/photo/trees-during-day-3573351/",
      "photographer": "Lukas Rodriguez",
      "photographer_url": "https://www.pexels.com/@lukas-rodriguez-1845331",
      "photographer_id": 1845331,
      "avg_color": "#374824",
      "src": {
        "original": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png",
        "large2x": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
        "large": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&h=650&w=940",
        "medium": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&h=350",
        "small": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&h=130",
        "portrait": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800",
        "landscape": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200",
        "tiny": "https://images.pexels.com/photos/3573351/pexels-photo-3573351.png?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=200&w=280"
      },
      "liked": false,
      "alt": "Brown Rocks During Golden Hour"
    }
  ],
  "next_page": "https://api.pexels.com/v1/search/?page=2&per_page=1&query=nature"
}

I wanted each of the things in the response to be accessed as class object so tried to make separate custom object, my types.py

but i can't access objects like photos1.alt

my client function:

    def _make_request(
            self,
            path: str,
            method: str = "get",
            **kwargs: Dict[Any, Any]
        ) -> Tuple[Union[Dict, str], requests.Response]:
    
            header = {'Authorization': self._token}
            req = self.session.request(method, f'{self._host}/{path}', headers=header,**kwargs)
    
            if req.status_code in [200, 201]:
                try:
                    return req.json(), req
                except JSONDecodeError:
                    return req.text, req
            elif req.status_code == 400:
                raise PexelsError("Bad Request Caught")
            else:
                raise PexelsError(f"{req.status_code} : {req.reason}")
    
        def search_photos(
            self, 
            query: str, 
            orientation: str = "", 
            size:str = "",
            color: str = "",
            locale: str = "",
            page: int = 1,
            per_page: int = 15,
            **kwargs
        ) -> SearchResponse:
    
            data, req = self._make_request(f"search?query={query}")
            return SearchResponse(**data)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

骄兵必败 2025-02-17 15:24:21

在您的searchResponse代码中,照片是字典列表,而不是照片实例列表。尝试使用列表comp来实例化多个照片实例,

self.photo = [Photo(**p) for p in photos]

然后您可以访问这样的实例的alt

photo[0].alt

the Off class定义的

class SearchResponse(PexelsType):

photos = List[Photo]
"A list of `Photo` object"
page = int
"The current page number"
per_page = int
"The number of results returned with each page"
total_results = int
"The total number of results for the request"
prev_page = str
"URL for the previous page of results, if applicable"
next_page = str
"URL for the next page of results, if applicable"

def __init__(
    self,
    photos: List[Photo],
    page: int,
    per_page: int,
    total_results: int,
    prev_page: str = "",
    next_page: str = "",
    **kwargs
    ):
    self.photos = [Photo(**photo) for photo in photos ]
    self.page = page
    self.per_page = per_page
    self.total_results = total_results
    self.prev_page = prev_page
    self.next_page = next_page

唯一更改是self.photos

In your SearchResponse code, photos is a list of dictionary and not a list of Photo instance. Try using a list comp to instantiate multiple Photo instance

self.photo = [Photo(**p) for p in photos]

you can then access the alt of an instance like this

photo[0].alt

The full class definition

class SearchResponse(PexelsType):

photos = List[Photo]
"A list of `Photo` object"
page = int
"The current page number"
per_page = int
"The number of results returned with each page"
total_results = int
"The total number of results for the request"
prev_page = str
"URL for the previous page of results, if applicable"
next_page = str
"URL for the next page of results, if applicable"

def __init__(
    self,
    photos: List[Photo],
    page: int,
    per_page: int,
    total_results: int,
    prev_page: str = "",
    next_page: str = "",
    **kwargs
    ):
    self.photos = [Photo(**photo) for photo in photos ]
    self.page = page
    self.per_page = per_page
    self.total_results = total_results
    self.prev_page = prev_page
    self.next_page = next_page

The only change is self.photos

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文