• python脚本将json文件生成C语言结构体


    1.引言

    以前用过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 \n")
        fp.write("#include \n")
        fp.write("#include \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)
    
    
    
  • 相关阅读:
    ubuntu配置ffmpeg环境
    2024022502-数据库绪论
    在conda的环境中安装Jupyter及其他软件包
    【教学类-19-01】20221127《ABAB规律排序-A4竖版2份》(中班)
    web3之链上情报平台Arkham
    Centos7 docker搭建onlyoffice
    2023年【电工(技师)】试题及解析及电工(技师)模拟考试题
    Spring——五大类注解和方法注解详解
    数据结构--不定长顺序表
    图片码二次渲染绕过
  • 原文地址:https://www.cnblogs.com/yoshinb/p/16669743.html