使用Pydantic模型向Redis写入哈希时出现数据错误
问题原因
触发redis.exceptions.DataError: A tuple item must be str, int, float or bytes的核心原因有两个:
- UUID类型不兼容:
Site.id是UUID对象,Redis哈希仅支持存储str、int、float或bytes类型,无法直接识别UUID。 - 嵌套模型未序列化:
Site.coordinate是Coordinate模型实例,调用site.dict()后该字段会被转为嵌套字典,而Redis哈希的value不支持嵌套字典结构。
解决方案
针对这两个问题,提供两种实用修复方式:
方式一:全局JSON序列化
直接利用Pydantic的json()方法将整个模型序列化为JSON字符串,再解析为字典,自动完成所有复杂类型到字符串的转换:
import json def insert(self, site: Site, **kwargs): """Insert a Site into Redis.""" hash_key = self.key_schema.site_hash_key(str(site.id)) site_ids_key = self.key_schema.site_ids_key() client = kwargs.get('pipeline', self.redis) # 序列化模型为JSON后转字典,所有复杂类型转为Redis兼容的字符串 site_data = json.loads(site.json()) client.hset(hash_key, mapping=site_data) client.sadd(site_ids_key, str(site.id))
方式二:单独处理特殊字段
如果不需要全局序列化,可针对性处理UUID和嵌套模型字段:
import json def insert(self, site: Site, **kwargs): """Insert a Site into Redis.""" hash_key = self.key_schema.site_hash_key(str(site.id)) site_ids_key = self.key_schema.site_ids_key() client = kwargs.get('pipeline', self.redis) site_dict = site.dict() # 将UUID转为字符串 site_dict['id'] = str(site_dict['id']) # 将嵌套Coordinate模型转为JSON字符串 if site_dict['coordinate'] is not None: site_dict['coordinate'] = json.dumps(site_dict['coordinate']) client.hset(hash_key, mapping=site_dict) client.sadd(site_ids_key, str(site.id))
可选优化(Pydantic v2)
若使用Pydantic v2,可直接调用model_dump(mode='json')简化序列化步骤,它会自动将UUID转为字符串,再配合JSON序列化处理嵌套模型:
import json def insert(self, site: Site, **kwargs): """Insert a Site into Redis.""" hash_key = self.key_schema.site_hash_key(str(site.id)) site_ids_key = self.key_schema.site_ids_key() client = kwargs.get('pipeline', self.redis) site_data = site.model_dump(mode='json') if site_data['coordinate'] is not None: site_data['coordinate'] = json.dumps(site_data['coordinate']) client.hset(hash_key, mapping=site_data) client.sadd(site_ids_key, str(site.id))
内容的提问来源于stack exchange,提问作者haku
相关产品推荐
相关产品推荐

