Python json文件生成C语言结构体
蘑菇王国大聪明 人气:01.引言
以前用过python脚本根据excel生成相关C语言代码,其实本质就是文件的读写,主要是逻辑问题,这次尝试将json文件生成C语言的结构体。
2.代码
这是一个json文件,生成这个结构体的本质是深度优先遍历,为了适应最复杂的情况,随便写了一个json文件(大家也可以根据需求自己改,我是自己写的,成功之后就去生产随机json的网站测试,目前没有啥问题,如果大家可以发现问题欢迎指出,在此感谢!)
{ "BE1":{ "apb_base_addr" : "0x80000000", "stt_base_addr" : "0x40000000", "size_type" : { "REG": 64, "LUT": 64, "STT": 128 }, "module": [ "BE_SYS", "BE_BIU", "DEC", "BLC", "LSC", "DGAIN", "AESTAT", "AWBSTAT", "AWB", "BDRC", "DM", "GAMMA", "RGBDITHER", "CSC", "SHP", "Y2RCSC", "CDS", "YUVDITHER","YUVDITHER" ], "nums": [ 1,2,6,4,3,6 ], "tests" : [{"test1": 100, "test2": 200, "test3": 300 } , {"test1": 400, "test2": 500, "test3": 600 }], "repeat":{ "a1" : {"test1": 100, "test2": 200, "test3": 300 } , "b1" : {"test4": 400, "test5": 500, "test6": 600 } } }, "PE1" : 0, "BE2":{ "apb_base_addr" : "0x80000000", "stt_base_addr" : "0x40000000", "size_type" : { "REG": 64, "LUT": 64, "STT": 128 }, "module": [ "BE_SYS", "BE_BIU", "DEC", "BLC", "aaa", "qwe", "AESTAT", "AWBSTAT", "AWB", "BDRC", "DM", "GAMMA", "RGBDITHER", "abc", "SHP", "Y2RCSC", "CDS", "YUVDITHER","YUVDITHER" ], "nums": [ 1,2,3,4,5,6 ], "tests" : [{"test1": 100, "test2": 200, "test3": 300 } , {"test1": 400, "test2": 500, "test3": 600 }], "repeat":{ "a1" : {"test1": 100, "test2": 200, "test3": 300 } , "b1" : {"test4": 400, "test5": 500, "test6": 600 } } }, "PE2" : 0 }
python脚本:
json解析代码:
################################################################################# # Company: # Engineer: # Create Date: 2022/7/25 # Project Name: # Design Name: # Module Name: json_parse # Description: # parse json file # Dependencies: # # Record: # Revision Date Description # v0.1 2022/7/25 parse json # Additional Comments: ################################################################################## import json def is_addr(addr): return (addr.find("0x") == 0) and (addr[2:-1].isdigit()) def is_array(node): if ((node.find("{") != -1) and (node.find("}") != -1)): if ((node.find("[") != -1) and (node.find("]") != -1) and (node.find("}") + 1 == node.find("["))): return True if ((node.find("(") != -1) and (node.find(")") != -1) and (node.find("}") + 1 == node.find("["))): return True return False def is_number(value): return value.isdigit() def is_struct_array(node, member_list): if((is_array(node)) and (member_list[-1] != node)): return True return False def is_number_array(node, member_list): if((is_array(node)) and (member_list[-1] == node)): return True return False def load_json(fp): try: data = json.load(fp) except Exception as e: print("This is not a json file! %s" % e) return "" return data def analyze_data(data, result, members): if isinstance(data, dict): for k, v in data.items(): analyze_data(v, result + "->get{\"%s\"}" % str(k), members) elif isinstance(data, (list, tuple)): for i in range(len(data)): analyze_data(data[i], result + "[%s]" % i, members) else: members.append(result + "=" + str(data)) def get_members(fp, members): data = load_json(fp) if data != "": analyze_data(data, "{\"json_config\"}", members) def get_max_depth(members): max_depth = 0 for i in members: max_depth = max(max_depth, len(i.split("->")) - 1) return max_depth def get_member_lists(members_array): member_lists = [] for member in members_array: member_list = member.split("->") member_lists.append(member_list) return member_lists def get_node_name(node, format): node_name_first = node.find("{\"") + 2 node_name_end = node.find("\"}") node_name = node[node_name_first:node_name_end] if format == "array": if ((node.find("[") != -1 and node.find("]") != -1)): index_1 = node.find("[") + 1 index_2 = node.find("]") node_name += "[" + node[index_1:index_2] + "]" return node_name def get_array_index(node): index_left = node.find("[") + 1 index_right = node.find("]") array_index = node[index_left:index_right] return array_index def check_value(value): if value.count(".") != 1: if value.isdigit(): return "int" elif value.count("-") == 1 and value.startswith("-"): num = value.split("-")[-1] if num.isdigit(): return "int" else: return check_bool(value) else: return check_bool(value) else: left = value.split(".")[0] right = value.split(".")[1] if right.isdigit(): if left.isdigit(): return "double" elif left.count("-") == 1 and left.startswith("-"): left_num = left.split("-")[-1] if left_num.isdigit(): return "double" else: return check_bool(value) else: return check_bool(value) else: return check_bool(value) def check_bool(value): if value.title() in ("True", "On"): return "bool" elif value.title() in ("False", "Off"): return "bool" elif is_addr(value): return "unsigned int" else: return "char *" def get_type(node, member_list): if is_number_array(node, member_list): value = node.split("=")[-1] return "array " + check_value(value) if(node.find("=") != -1): value = node.split("=")[-1] return check_value(value) if is_struct_array(node, member_list): for i, temp in enumerate(member_list): if(temp == node): node_child = member_list[i+1] return "array " + "struct " + get_node_name(node, "") + "_s" return "struct " + get_node_name(node, "") + "_s" def find_fathers(node_pre_names, node_name, node_father_names): node_pres = node_father_names.get(node_name, False) if (node_pres): for i in node_pres: if i== node_pre_names: return True return False def get_node_info_list(member_lists): node_info_list = [] node_father_names = {} row = len(member_lists) flag = 0 # json for i, member_list in enumerate(member_lists): for j, node in enumerate(member_list): node_info = {} node_name = get_node_name(node, "") node_pre_names = [] node_pres = [] if j == 0 and flag == 1: continue # root if j == 0: node_info["name"] = node_name child_names = [] node_info["value"] = "" child_type = {} number = 0 if node.find("[") != -1 and node.find("]") != -1: index_l = node.find("[") index_r = node.find("]") last_node = member_lists[-1][0] number = max(number, int(last_node[index_l + 1: index_r])) for index in range(i, row): if (len(member_lists[index]) <= j): break if (member_lists[index][j] != node): break node_child = member_lists[index][j + 1] child_name = get_node_name(node_child, "") child_names.append(child_name) child_type[child_name] = get_type(node_child, member_lists[index]) child_names = list(set(child_names)) node_info["child_name"] = child_names node_info["child_num"] = len(child_names) node_info["child_type"] = child_type node_info["self_type"] = "struct " + node_name + "_s" node_info["depth"] = j node_info["json_number"] = number node_info_list.append(node_info) flag = 1 continue index = j - 1 while (index >= 0): node_pre_name = get_node_name(member_list[index], "array") node_pre_names.append(node_pre_name) index -= 1 if (j > 0 and (not find_fathers(node_pre_names, node_name, node_father_names)) ) : node_info["name"] = node_name node_info["father_name"] = node_pre_names node_pres.append(node_pre_names) node_father_names[node_name] = node_pres # leaf node (array) if (is_number_array(node, member_list)): node_value_list = [] for index in range(i, row): if (len(member_lists[index]) <= j): break if (get_node_name(member_lists[index][j], "") != node_name): break node_value_list.append(member_lists[index][j][member_lists[index][j].find("=") + 1:]) node_info["value"] = node_value_list for i in node_value_list: node_info["self_type"] = "array " + check_value(i) break node_info["child_num"] = len(node_value_list) node_info["depth"] = j node_info_list.append(node_info) continue # leaf node (value) if (node.find("=") != -1): node_value = node[node.find("=") + 1:] node_info["value"] = node_value node_info["self_type"] = get_type(node, member_list) node_info["depth"] = j node_info_list.append(node_info) continue # struct array if (is_struct_array(node, member_list)): child_names = [] node_info["value"] = "" child_type = {} arr_index = "0" for index in range(i, row): if (len(member_lists[index]) <= j): break if (get_node_name(member_lists[index][j], "") != node_name): break arr_index = get_array_index(member_lists[index][j]) node_child = member_lists[index][j + 1] child_name = get_node_name(node_child, "") child_names.append(child_name) child_type[child_name] = get_type(node_child, member_list) node_info["self_type"] = "array " + "struct " + node_name + "_s" child_names = list(set(child_names)) node_info["child_name"] = child_names node_info["child_num"] = int(arr_index) + 1 node_info["child_type"] = child_type node_info["depth"] = j node_info_list.append(node_info) continue # dict json child_names = [] node_info["value"] = "" child_type = {} for index in range(i, row): if (len(member_lists[index]) <= j): break if (member_lists[index][j] != node): break node_child = member_lists[index][j + 1] child_name = get_node_name(node_child, "") child_names.append(child_name) child_type[child_name] = get_type(node_child, member_lists[index]) child_names = list(set(child_names)) node_info["child_name"] = child_names node_info["child_num"] = len(child_names) node_info["child_type"] = child_type node_info["self_type"] = "struct " + node_name + "_s" node_info["depth"] = j node_info_list.append(node_info) return node_info_list def get_nodes_info_from_jsonFile(file_path): members_array = [] with open(file_path, "r+") as fp: get_members(fp, members_array) max_depth = get_max_depth(members_array) member_lists = get_member_lists(members_array) node_info_list = get_node_info_list(member_lists) return (node_info_list, max_depth)
代码生成部分:
################################################################################# # Company: # Engineer: # Create Date: 2022/7/25 # Project Name: # Design Name: # Module Name: gen_code # Description: # gen header file and config file from json file # Dependencies: # # Record: # Revision Date Description # v0.1 2022/7/25 File Created # Additional Comments: ################################################################################## from utils.json_parse import * def get_nodeinfo_dict(node_info_list): node_info_dict = {} for i in node_info_list: data_list = [] name = i["name"] if(node_info_dict.get(name)): data_list = node_info_dict.get(name) data_list.append(i) node_info_dict[name] = data_list return node_info_dict def gen_struct(node_info, node_info_dict, fp): node_name = node_info["name"] fp.write( '/* Define the struct %s_s */\n' %node_name + 'struct %s_s\n' %node_name + '{\n' ) child_names = node_info["child_name"] child_types = node_info["child_type"] for child_name in child_names: child_type = child_types[child_name] # if array if (child_type.find("array") != -1): # find same node index = 0 for i, j in enumerate(node_info_dict[child_name]): if j["name"] == node_name \ and j["self_type"] == node_info["self_type"] \ and j["child_types"] == node_info["child_types"]: index = i child_child_num = node_info_dict[child_name][index]["child_num"] child_name += "[" + str(child_child_num) + "]" + ";" child_type = child_type.lstrip("array ") fp.write( '\t%s\t' % child_type.ljust(20) + child_name.ljust(30) + ' /* '.ljust(5) + child_name.rsplit(";")[0].ljust(15) + ' */\n' ) continue child_name += ";" fp.write( '\t%s\t' % child_type.ljust(20) + child_name.ljust(30) + ' /* '.ljust(5) + child_name.rsplit(";")[0].ljust(15) + ' */\n' ) fp.write( '}; \n\n' ) def get_depth_list(node_info_list, max_depth): depth_list = [[] for x in range(max_depth)] for node_info in node_info_list: depth = node_info["depth"] depth_list[depth-1].append(node_info) return depth_list def is_same_father(node1, node2): if(node1["father_name"] == node2["father_name"]): return True return False # not same node but same name and type def is_same_name_and_type(gened_nodes, node): node_name = node["name"] processed = gened_nodes.get(node_name, False) if(not processed): if(not is_same_father(processed, node) and processed["self_type"] == node["self_type"]): return True return False def is_same_struct(gened_nodes, node): node_name = node["name"] processed = gened_nodes.get(node_name) if (processed != None): processed = gened_nodes.get(node_name) if processed["child_type"] == node["child_type"]: return True return False def get_father_str(node_info): if(node_info["value"] != ""): fathers = list(reversed(node_info["father_name"])) name = node_info["name"] ret = "" for val in fathers: ret += val + "." # array if (node_info["self_type"].find("array") != -1): temp_name = "" for val in fathers: if(val.find("[") != -1 and val.find("]") != -1): index_left = val.find("[") index_right = val.find("]") val = val[:index_left] + val[index_left+1:index_right] temp_name += val + "_" temp_name += name if(node_info["self_type"].find("*") != -1): temp = node_info["self_type"].lstrip("array ") + temp_name else: temp = node_info["self_type"].lstrip("array ") + " " + temp_name child_num = node_info["child_num"] temp += "[" + str(child_num) + "]" + " = " + "{" value_list = node_info["value"] for i, j in enumerate(value_list): if (i == len(value_list) - 1): if (check_value(value_list[0]) != "char *"): temp += j else: temp += "\"" + j + "\"" continue if (check_value(value_list[0]) != "char *"): temp += j + ", " else: temp += "\"" + j + "\""+ ", " temp += "};\n\t" ret += name ret = temp + "memcpy(" + temp_name + ", " + ret + ", sizeof(" + temp_name + "));" return ret # not array val = node_info["value"] if (check_value(val) != "char *"): if(val == "True"): val = "true" if(val == "False"): val = "false" else: val = "\"" + val + "\"" ret += name + " = " + val +";" return ret return def define_struct(node_info_dict, fp): node_info_config = node_info_dict["json_config"][0] if (node_info_config["json_number"] != 0): json_number = node_info_config["json_number"] fp.write("\t%s %s[%s];\n" % (node_info_config["self_type"], node_info_config["name"], str(json_number + 1))) else: fp.write("\t%s %s;\n" % (node_info_config["self_type"], node_info_config["name"])) def generate_struct_h(gened_nodes, node_info_list, node_info_dict, fp): fp.write("#ifndef __JSON_CONFIG_H\n") fp.write("#define __JSON_CONFIG_H\n") fp.write("#include <stdio.h>\n") fp.write("#include <stdlib.h>\n") fp.write("#include <string.h>\n\n") for node_info in node_info_list: node_name = node_info["name"] if node_info["value"] == "": # not generated if not is_same_struct(gened_nodes, node_info): gen_struct(node_info, node_info_dict, fp) gened_nodes[node_name] = node_info node_info_config = node_info_dict["json_config"][0] if (node_info_config["json_number"] != 0): fp.write("%s *config_init(void);\n" %node_info_config["self_type"]) else: fp.write("%s config_init(void);\n" %node_info_config["self_type"]) fp.write("#endif") def generate_struct_init(node_info_dict, node_info_list, fp): node_info_config = node_info_dict["json_config"][0] fp.write("#include \"json_config.h\" \n\n") # TODO if (node_info_config["json_number"] != 0): fp.write("%s *config_init(void)\n" %node_info_config["self_type"]) else: fp.write("%s config_init(void)\n" %node_info_config["self_type"]) fp.write("{\n") # define struct define_struct(node_info_dict, fp) for node_info in node_info_list: ret = get_father_str(node_info) if ret == None: continue fp.write("\t" + ret + "\n") fp.write("\treturn %s;\n" %node_info_config["name"]) fp.write("}\n") def generate_test(node_info_dict, test_path): with open(test_path, "w") as fp: fp.write("//******************************************************************************\n\ // Copyright : Copyright (C) 2022, NIOd.\n\ // File name : json_test.c \n\ // Author : yoshi.shao \n\ // Version : 1.0 \n\ // Date : 2022-07-25 \n\ // Description : test \n\ // History : \n\ //******************************************************************************\n\n") fp.write("#include \"json_config.h\"\n\n") fp.write("int main(void)\n{\n") node_info_config = node_info_dict["json_config"][0] if (node_info_config["json_number"] != 0): fp.write("\t%s *%s = " % (node_info_config["self_type"], node_info_config["name"])) else: fp.write("\t%s %s = " % (node_info_config["self_type"], node_info_config["name"])) fp.write("config_init();\n") fp.write("\treturn 0;\n") fp.write("}\n") def generate_all(json_path, file_path, init_path, test_path): (node_info_list, max_depth) = get_nodes_info_from_jsonFile(json_path) node_info_dict = get_nodeinfo_dict(node_info_list) node_info_list = list(reversed(node_info_list)) gened_nodes = {} # generate struct.h with open(file_path, "w") as fp: fp.write("//****************************************************************************** \n\ // Copyright : Copyright (C) 2022, NIOd.\n\ // File name : json_config.h \n\ // Author : yoshi.shao \n\ // Version : 1.0 \n\ // Date : 2022-07-25 \n\ // Description : Define all struct \n\ // History : \n\ //******************************************************************************\n\n") generate_struct_h(gened_nodes, node_info_list, node_info_dict, fp) with open(init_path, "w") as fp: fp.write("//******************************************************************************\n\ // Copyright : Copyright (C) 2022, NIOd.\n\ // File name : json_config.c \n\ // Author : yoshi.shao \n\ // Version : 1.0 \n\ // Date : 2022-07-25 \n\ // Description : init json struct \n\ // History : \n\ //******************************************************************************\n\n") generate_struct_init(node_info_dict, node_info_list, fp) generate_test(node_info_dict, test_path)
加载全部内容