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 <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)

以上就是Python实现将json文件生成C语言的结构体的脚本分享的详细内容,更多关于Python json文件生成C语言结构体的资料请关注其它相关文章!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容