2024-10-23 11:10:17 +08:00
|
|
|
|
# -*- encoding:utf-8 -*-
|
2024-10-12 18:01:59 +08:00
|
|
|
|
import re
|
2024-10-23 11:10:17 +08:00
|
|
|
|
import json
|
2024-10-22 21:02:54 +08:00
|
|
|
|
|
|
|
|
|
def preprocess_data(data):
|
2024-10-23 11:10:17 +08:00
|
|
|
|
# 根据需要预处理数据,这里假设原始数据已经是一个字典
|
|
|
|
|
return data
|
2024-10-22 21:02:54 +08:00
|
|
|
|
|
|
|
|
|
def transform_json(data):
|
|
|
|
|
result = {}
|
|
|
|
|
temp = {0: result} # 初始化根字典
|
2024-10-23 11:10:17 +08:00
|
|
|
|
data = preprocess_data(data)
|
|
|
|
|
|
|
|
|
|
# 首先, 创建一个临时字典用于检查是否存在三级标题
|
2024-10-22 21:02:54 +08:00
|
|
|
|
has_subkey = {}
|
|
|
|
|
for key in data.keys():
|
|
|
|
|
parts = key.split('.')
|
|
|
|
|
if len(parts) > 2 and parts[1]:
|
2024-10-23 11:10:17 +08:00
|
|
|
|
parent_key = '.'.join(parts[:2])
|
2024-10-22 21:02:54 +08:00
|
|
|
|
has_subkey[parent_key] = True
|
|
|
|
|
|
|
|
|
|
for key, value in data.items():
|
|
|
|
|
match = re.match(r'(\d+)(?:\.(\d+))?(?:\.(\d+))?', key)
|
|
|
|
|
if match:
|
|
|
|
|
levels = [int(l) for l in match.groups() if l is not None]
|
2024-10-23 11:10:17 +08:00
|
|
|
|
current_level = len(levels)
|
|
|
|
|
parent = temp.get(current_level - 1, result)
|
|
|
|
|
|
|
|
|
|
# 获取标题内容
|
|
|
|
|
if current_level == 1:
|
|
|
|
|
# 一级标题
|
|
|
|
|
parent[value] = {}
|
|
|
|
|
temp[current_level] = parent[value]
|
|
|
|
|
elif current_level == 2:
|
|
|
|
|
# 二级标题
|
|
|
|
|
if has_subkey.get(key, False):
|
|
|
|
|
parent[value] = {}
|
2024-10-22 21:02:54 +08:00
|
|
|
|
else:
|
2024-10-23 11:10:17 +08:00
|
|
|
|
parent[value] = value # 如果没有子键,直接赋值内容
|
|
|
|
|
temp[current_level] = parent[value]
|
|
|
|
|
elif current_level == 3:
|
|
|
|
|
# 三级标题
|
2024-10-22 21:02:54 +08:00
|
|
|
|
if isinstance(parent, dict):
|
2024-10-23 11:10:17 +08:00
|
|
|
|
# 确保父级是一个字典
|
|
|
|
|
parent[value] = value
|
2024-10-22 21:02:54 +08:00
|
|
|
|
elif isinstance(parent, list):
|
|
|
|
|
parent.append(value)
|
2024-10-23 11:10:17 +08:00
|
|
|
|
temp[current_level] = value
|
|
|
|
|
else:
|
|
|
|
|
# 处理无法匹配的键
|
|
|
|
|
print(f"无法匹配的键: {key}")
|
2024-10-12 18:01:59 +08:00
|
|
|
|
|
2024-10-22 21:02:54 +08:00
|
|
|
|
def remove_single_item_lists(node):
|
|
|
|
|
if isinstance(node, dict):
|
|
|
|
|
for key in list(node.keys()):
|
|
|
|
|
node[key] = remove_single_item_lists(node[key])
|
|
|
|
|
if isinstance(node[key], list) and len(node[key]) == 1:
|
|
|
|
|
node[key] = node[key][0]
|
|
|
|
|
return node
|
2024-10-12 18:01:59 +08:00
|
|
|
|
|
2024-10-22 21:02:54 +08:00
|
|
|
|
return remove_single_item_lists(result)
|
2024-10-12 18:01:59 +08:00
|
|
|
|
|
2024-10-22 21:02:54 +08:00
|
|
|
|
# 示例数据
|
|
|
|
|
data = {
|
2024-10-23 11:10:17 +08:00
|
|
|
|
"20.": "投标文件的式样和签署",
|
|
|
|
|
"20.1": "投标文件的式样:投标人应准备一份投标文件正本、电子文件和投标须知前附表中规定数目的副本,投标文件的副本可采用正本的复印件。每套投标文件须清楚地标明“正本”或“副本”。若副本与正本不符,以正本为准,装订如下:序号投标文件名称装订备注1唱标信封/投标报价一览表(加盖公章)、《投标保证金汇入情况说明》(加盖公章)、投标保证金缴付凭证复印件(加盖公章)2电子文件含价格文件、商务技术文件3价格文件独立装订成册含正、副本4商务技术文件商务文件和技术文件可一起独立装订成册,也可含正、副本以分开独立装订成册",
|
|
|
|
|
"20.2": "投标文件的装订要求:投标报价表部分必须单独装订,若将投标报价表与商务、技术部分等内容合为装订或在商务、技术部分等内容出现投标报价,则作无效投标处理。",
|
|
|
|
|
"20.3": "电子文件用MSWORD/EXCEL简体中文版制作,内容包括:由投标人自行制作的与正本文件一致的所有文件。电子文件由CD-R光盘或优盘储存,放在唱标信封内。",
|
|
|
|
|
"20.4": "投标文件的签署:",
|
|
|
|
|
"20.4.1": "投标文件的正本需打印或用不褪色墨水书写,副本可以复印。授权代表须将以书面形式出具的《法定代表人授权委托书》附在投标文件中。投标人的投标文件必须按照招标文件“第六部分投标文件格式”已明示法定代表人(或其授权代表)签署和盖章处,必须进行签字(或盖私章)和盖公章,否则视为无效投标。",
|
|
|
|
|
"20.4.2": "投标文件中的任何重要的插字、涂改和增删,必须由法定代表人或经其正式授权的代表在旁边签署才有效。",
|
|
|
|
|
"20.4.3": "投标文件的“正本”及所有“副本”的封面及每一页都必须由投标人加盖公章或骑缝章或法定代表人(或其授权代表)签署,对于未按要求盖章或签署的投标文件,均作无效投标处理。投标文件的“正本”及所有“副本”的封面及每一页都必须由投标人加盖公章或骑缝章或法定代表人(或其授权代表)签署,对于未按要求盖章或签署的投标文件,均作无效投标处理。"
|
2024-10-22 21:02:54 +08:00
|
|
|
|
}
|
2024-10-12 18:01:59 +08:00
|
|
|
|
|
2024-10-23 11:10:17 +08:00
|
|
|
|
transformed = transform_json(data)
|
|
|
|
|
print(json.dumps(transformed, ensure_ascii=False, indent=4))
|