将XML文本转化为Pydantic对象

 近期项目需要对接TCP协议,其负载采用XML格式,尝试用xml.etree.ElementTree解析,感觉获取相应字段内容的过程较为繁琐,且再将字段的内容赋值到对象中也需要大量的手工。考虑到对象映射的易用性和Pydantic比较强的校验器等功能,因此查了下XML->Pydantic的解决方案。研究了pydantic-xml这个库,感觉使用文档不够详细。后来又参看这篇文章发现通过xmltodict是一个很好的中转方案,再结合Pydantic类的model_validate函数,可以比较完美的实现有XML文本到Pydantic对象的转化。示例代码如下:

# codeing: utf-8
# author: jsnjhhy@126.com

import xmltodict
from pydantic import BaseModel, Field
from datetime import datetime

payload="""
<PatrolDevice>
    <Type>1002</Type>
    <Command>1</Command>
    <Time>2023-01-01 00:00:01</Time>
    <Items>
        <MotionState>0</MotionState>
        <PosX>0.0</PosX>
        <PosY>0.0</PosY>
        <PosZ>0.0</PosZ>
    </Items>
</PatrolDevice>
"""

class Items(BaseModel):
    motionState: int = Field(alias="MotionState")
    posX: float = Field(alias="PosX")
    posY: float = Field(alias="PosY")
    posZ: float = Field(alias="PosZ")

class PatrolDevice(BaseModel):
    type: int= Field(alias="Type")
    command: int= Field(alias="Command")
    time: datetime= Field(alias="Time")
    items: Items= Field(alias="Items")



payload_dict = xmltodict.parse(payload) 

payload_pydantic =PatrolDevice.model_validate(payload_dict ['PatrolDevice']) 

运行结果如下:

Trouble Shooting:

<?xml version="1.0" encoding="UTF-8" ?>

xmltodict只能处理纯粹XML负载,对于上面XML描述头似乎无法处理,转化成dict时,需要将描述头所在的一行去掉。

在 FastAPI 中,如果路径操作函数返回的是 `list` 类型的数据,FastAPI 会自动将其转换为 JSON 格式,并以 `application/json` 作为 `Content-Type` 响应给客户端[^2]。这种处理方式适用于大多数场景,例如返回一组用户数据、商品列表等。 ### 返回 list 类型的响应示例 以下是一个返回 `list` 类型的示例: ```python from fastapi import FastAPI app = FastAPI() @app.get("/items/") def read_items(): return ["item1", "item2", "item3"] ``` 当访问 `/items/` 接口时,FastAPI 会自动将列表 `["item1", "item2", "item3"]` 转换为 JSON 格式并返回给客户端,响应内容如下: ```json ["item1", "item2", "item3"] ``` ### 自定义响应内容类型 如果希望返回的响应不是默认的 `application/json`,而是其他类型的内容(例如 XML 或纯文本),可以使用 `Response` 对象手动构造响应内容。例如,返回纯文本格式的列表内容: ```python from fastapi import FastAPI from fastapi.responses import PlainTextResponse app = FastAPI() @app.get("/items/", response_class=PlainTextResponse) def read_items(): return ", ".join(["item1", "item2", "item3"]) ``` 此时,接口返回的 `Content-Type` 将是 `text/plain`,响应内容为: ``` item1, item2, item3 ``` ### 返回包含嵌套数据结构的 list 除了简单的字符串列表,还可以返回包含复杂数据结构的 `list`,例如嵌套字典或 Pydantic 模型实例。FastAPI 会自动处理这些数据类型的序列化操作[^3]。例如: ```python from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Item(BaseModel): id: int name: str @app.get("/items/") def read_items(): return [ {"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"} ] ``` 上述代码返回的响应将自动转换为 JSON 格式,内容如下: ```json [ {"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"} ] ``` 如果返回的是 Pydantic 模型的实例列表,FastAPI 也会自动将其转换为 JSON 格式: ```python @app.get("/items/", response_model=list[Item]) def read_items(): return [ Item(id=1, name="Item 1"), Item(id=2, name="Item 2") ] ``` ### 处理大型列表数据 在处理大型列表数据时,建议使用分页机制来限制返回的数据量,避免一次性返回过多数据导致性能问题。例如,可以通过查询参数 `skip` 和 `limit` 来实现分页功能: ```python @app.get("/items/") def read_items(skip: int = 0, limit: int = 10): items = ["item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8", "item9", "item10"] return items[skip:skip + limit] ``` 通过访问 `/items?skip=0&limit=5`,可以获取前 5 个条目;访问 `/items?skip=5&limit=5`,可以获取后 5 个条目。 ### 异常处理 在某些情况下,返回的 `list` 可能为空或引发错误。为了提高 API 的健壮性,可以结合 `try-except` 块来捕获异常,并返回适当的错误信息: ```python from fastapi import FastAPI, HTTPException app = FastAPI() @app.get("/items/") def read_items(): try: items = [] if not items: raise HTTPException(status_code=404, detail="Items not found") return items except Exception as e: raise HTTPException(status_code=500, detail=str(e)) ``` 在这种情况下,如果列表为空,将返回 404 错误;如果发生其他异常,将返回 500 错误。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值