You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中精准实现字典/JSON与XML的双向转换并完整保留结构?

如何在Python中精准实现字典/JSON与XML的双向转换并完整保留结构?

我太懂你这种烦恼了!之前用dicttoxml和xmltodict做双向转换的时候,也踩过这个讨厌的“item嵌套+类型丢失”双坑——好好的结构平白多了一层冗余的item键,连整数都变成了字符串,要是写后处理代码清理吧,又怕误改合法字段,真心闹心。不过别担心,咱们通过调整两个库的参数配置,就能完美解决这些问题,完全不用额外写复杂的后处理!

先给你说核心思路:要从“生成XML”和“解析XML”两个环节同时下手,既要让XML生成时避免无意义的<item>标签,也要让解析时自动还原原始结构和数据类型。

方案一:生成语义化XML(推荐,结构更清晰)

这个方案会把列表元素的标签从默认的<item>改成和父节点对应的单数形式(比如mydicts下面的元素用mydict),生成的XML更易读,解析时也能直接完美还原结构。

import xmltodict
import dicttoxml

# 自定义函数:把父节点的复数名转成单数(简单实现,复杂场景可以用inflect库优化)
def plural_to_singular(parent_key):
    return parent_key[:-1] if parent_key.endswith('s') else parent_key

# 原始JSON/字典
original_json = {
    "mydicts": [
        {"id": 1, "name": "alice"},
        {"id": 2, "name": "bob"}
    ]
}

# 1. JSON转XML:用自定义标签替换默认的<item>
xml_output = dicttoxml.dicttoxml(
    original_json,
    root=True,  # 保留根节点
    item_func=plural_to_singular,  # 列表元素用父键的单数标签
    attr_type=False  # 不生成冗余的type属性(比如type="int")
)
print("生成的XML:")
print(xml_output.decode('utf-8'))

# 2. XML转JSON:强制解析列表并还原类型
parsed_json = xmltodict.parse(
    xml_output,
    # 强制把单数标签的节点解析成列表(避免单个元素时变成字典)
    force_list=[plural_to_singular("mydicts")],
    attr_prefix='',  # 去掉属性前缀,避免不必要的嵌套
    cdata_key=''  # 不保留CDATA标记
)
# 去掉xmltodict默认的root节点外层
parsed_json = parsed_json['root']

# 额外处理:把XML解析出的字符串类型数字转回数值类型
def convert_types(data):
    if isinstance(data, dict):
        for k, v in data.items():
            if isinstance(v, str):
                if v.isdigit():
                    data[k] = int(v)
                elif '.' in v and all(part.isdigit() for part in v.split('.')):
                    data[k] = float(v)
            elif isinstance(v, list):
                for item in v:
                    convert_types(item)
    return data

parsed_json = convert_types(parsed_json)

print("\n解析后的字典:")
print(parsed_json)
print("\n和原始结构&类型完全一致:", parsed_json == original_json)

方案二:保留默认标签,解析时自动清理嵌套

如果你不想修改XML的标签格式,就想用默认的<item>,那可以用xmltodict的postprocessor参数自动去掉item的嵌套,同时还原数据类型:

import xmltodict
import dicttoxml

original_json = {
    "mydicts": [
        {"id": 1, "name": "alice"},
        {"id": 2, "name": "bob"}
    ]
}

# 1. JSON转XML:用默认的<item>标签(和你原来的代码逻辑一致)
xml_output = dicttoxml.dicttoxml(
    original_json,
    root=True,
    attr_type=False
)
print("生成的XML:")
print(xml_output.decode('utf-8'))

# 自定义后处理函数:去掉item嵌套+还原数据类型
def clean_and_convert(path, key, value):
    if key == 'item':
        # 把字符串数字转成数值类型
        for k, v in value.items():
            if isinstance(v, str):
                if v.isdigit():
                    value[k] = int(v)
                elif '.' in v and all(part.isdigit() for part in v.split('.')):
                    value[k] = float(v)
        # 返回None+值,相当于移除item键,直接保留内容
        return None, value
    return key, value

# 2. XML转JSON:自动清理item嵌套
parsed_json = xmltodict.parse(
    xml_output,
    force_list=['mydicts'],  # 强制mydicts为列表,避免单个元素时变成字典
    postprocessor=clean_and_convert,
    attr_prefix='',
    cdata_key=''
)
parsed_json = parsed_json['root']

print("\n解析后的字典:")
print(parsed_json)
print("\n和原始结构&类型完全一致:", parsed_json == original_json)

小提示

  • 方案一更推荐,因为生成的XML语义化更强,后续维护起来更方便;
  • 关于类型转换:XML本身没有数据类型的概念,所有内容都是文本,所以必须手动处理类型转换,上面的代码已经包含了基础的数字转换逻辑,复杂类型(比如布尔值)可以自己扩展;
  • 如果你有单个元素的列表(比如mydicts里只有一个字典),一定要用force_list强制解析成列表,否则xmltodict会把它转成普通字典,破坏原始结构。

备注:内容来源于stack exchange,提问作者funkmeister

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 13:33:03