Python中消息结构与内部结构的双向转换(非简单映射)
实现外部与内部消息结构的双向转换
听起来你需要的是一套结构化的消息映射转换逻辑,核心在于处理字段映射、字段位置调整和类型转换这几个关键点。我用Python给你写个可复用的实现示例,完全覆盖你提到的场景,而且很容易扩展到其他字段:
1. 外部转内部(入站转换)
首先处理外部消息到内部结构的转换,需要完成这几项核心操作:
- 重命名字段:
Person.name.first→Person.firstname,Person.name.last→Person.lastname - 调整字段位置:将根节点的
birth_date移到Person节点下 - 类型转换:把字符串日期转成
datetime.date对象,字符串数字转成整数类型
from datetime import datetime def external_to_internal(external_msg): # 提取外部消息中的Person和嵌套字段 person_external = external_msg.get("Person", {}) name_external = person_external.get("name", {}) # 构建内部格式的Person结构 internal_person = { "firstname": name_external.get("first"), "lastname": name_external.get("last"), # 处理日期字符串到date对象的转换 "birth": datetime.strptime(external_msg.get("birth_date"), "%Y.%m.%d").date(), # 处理字符串数字到整数的转换 "points": int(external_msg.get("points")) } # 组装最终的内部消息结构 internal_msg = { "Person": internal_person } return internal_msg # 测试示例 external_example = { "Person": { "name": { "first": "John", "last": "Smith" } }, "birth_date": "1997.01.12", "points": "330" } print(external_to_internal(external_example)) # 输出:{'Person': {'firstname': 'John', 'lastname': 'Smith', 'birth': datetime.date(1997, 1, 12), 'points': 330}}
2. 内部转外部(出站转换)
反向转换需要把内部结构还原成外部格式,也就是逆向执行入站的操作:
- 重命名字段:
Person.firstname→Person.name.first,Person.lastname→Person.name.last - 调整字段位置:将
Person.birth移回根节点 - 类型转换:把
date对象转成YYYY.MM.DD格式的字符串,整数转成字符串类型
def internal_to_external(internal_msg): # 提取内部消息中的Person字段 person_internal = internal_msg.get("Person", {}) # 构建外部格式的Person.name结构 external_name = { "first": person_internal.get("firstname"), "last": person_internal.get("lastname") } external_person = { "name": external_name } # 组装最终的外部消息结构 external_msg = { "Person": external_person, # 处理date对象到字符串的转换 "birth_date": person_internal.get("birth").strftime("%Y.%m.%d"), # 处理整数到字符串的转换 "points": str(person_internal.get("points")) } return external_msg # 测试反向转换 internal_example = { "Person": { "firstname": "John", "lastname": "Smith", "birth": datetime.date(1997, 1, 12), "points": 330 } } print(internal_to_external(internal_example)) # 输出:{'Person': {'name': {'first': 'John', 'last': 'Smith'}}, 'birth_date': '1997.01.12', 'points': '330'}
3. 可扩展优化建议
如果以后要处理更多字段或更复杂的映射规则,建议把映射逻辑抽离成配置字典,这样不用修改核心转换函数,维护起来更高效:
# 定义入站映射规则:目标路径 → 源配置(字段路径或带转换器的配置) INBOUND_MAPPING = { "Person.firstname": "Person.name.first", "Person.lastname": "Person.name.last", "Person.birth": {"source": "birth_date", "converter": lambda x: datetime.strptime(x, "%Y.%m.%d").date()}, "Person.points": {"source": "points", "converter": int} } # 基于映射规则的通用入站转换函数(简化版) def generic_external_to_internal(external_msg, mapping): internal_msg = {} for target_path, source_config in mapping.items(): target_parts = target_path.split('.') target_obj = internal_msg # 遍历目标路径,创建嵌套结构 for part in target_parts[:-1]: target_obj = target_obj.setdefault(part, {}) if isinstance(source_config, dict): # 处理带转换器的字段 source_val = external_msg.get(source_config["source"]) target_obj[target_parts[-1]] = source_config["converter"](source_val) else: # 处理直接字段映射 source_parts = source_config.split('.') source_val = external_msg for part in source_parts: source_val = source_val.get(part, {}) target_obj[target_parts[-1]] = source_val return internal_msg
这种方式的好处是,新增或修改字段映射只需要更新配置字典,核心转换逻辑保持稳定,适合复杂场景下的迭代维护。
内容的提问来源于stack exchange,提问作者André Paramés
相关产品推荐
相关产品推荐

