给定一个CerberusJSON模式文件,如何生成字典对象

58wvjzkj  于 2023-08-08  发布在  其他
关注(0)|答案(1)|浏览(106)

问题

我有一个Cerberus Json模式文件,我需要基于模式生成Json文件,并在给定data_types的情况下使用默认值。字典对象中的键_type是要检查的data_type。
Cerberus Json Schema示例

{
    "schema": {
        "vars": {
            "forest_config": {
                "_type": "list",
                "_required": false,
                "_not_empty": false,
                "_item_schema": {
                    "_type": "dict",
                    "always_create_dl_here": {
                        "_required": false,
                        "_type": "bool"
                    },
                    "ldap_domain": {
                        "_type": "string",
                        "_required": false
                    },
                    "dc_dn": {
                        "_type": "string",
                        "_required": true,
                        "_not_empty": true,
                        "_regex": "^(DC|O)=[\\w\\-\\. &]+(,(DC|O)=[\\w\\-\\. &]+)*$"
                    },
                    "user_ou": {
                        "_type": "string",
                        "_required": true,
                        "_not_empty": false,
                        "_regex": "^((CN|OU)=[\\w\\-\\. &]+(,(CN|OU)=[\\w\\-\\. &]+)*)?$"
                    },
                    "group_ou": {
                        "_type": "string",
                        "_required": true,
                        "_not_empty": false,
                        "_regex": "^((CN|OU)=[\\w\\-\\. &]+(,(CN|OU)=[\\w\\-\\. &]+)*)?$"
                    },
                    "dl_group_ou": {
                        "_type": "string",
                        "_required": true,
                        "_not_empty": false,
                        "_regex": "^((CN|OU)=[\\w\\-\\. &]+(,(CN|OU)=[\\w\\-\\. &]+)*)?$"
                    }
                }
            }
        }
    }
}

字符串
我试着做我自己的递归函数,但是我被卡住了

new_obj = {}
        def recursively_generate_schema_obj(dict_obj: Dict):
            if isinstance(dict_obj, dict):
                var_name = None
                for key, value in dict_obj.items():
                    if not str(key).startswith("_"):
                        var_name = key

                    if var_name and '_type' not in dict_obj:
                        new_obj[var_name] = {}
                    elif var_name and '_type' in dict_obj and dict_obj['_type'] == 'list':
                        new_obj[var_name] = [recursively_generate_schema_obj(dict_obj)]
                    else:
                        new_obj[var_name] = create_default_type_value(dict_obj['_type'])

                    recursively_generate_schema_obj(value)

        recursively_generate_schema_obj(schema_data)

    def get_default_value(data_type:str):
        if data_type == 'string':
            return ''
        elif data_type == 'dict':
            return {}
        elif data_type == 'bool':
            return False
        elif data_type == 'list':
            return []
        elif data_type == 'int':
            return 0
        elif data_type == 'enum': # this needs to be handled in the calling function
            return ''

代码当前输出

{'schema': {}, 'vars': {}, 'forest_config': {}, None: '', 'always_create_dl_here': {}, 'ldap_domain': {}, 'dc_dn': {}, 'user_ou': {}, 'group_ou': {}, 'dl_group_ou': {}}


这肯定是错的
应该是

{
    "schema": {
        "vars": {
            "forest_config": [
                {
                    "always_create_dl_here": false,
                    "ldap_domain": "",
                    "dc_dn": "",
                    "user_ou": "",
                    "group_ou": "",
                    "dl_group_ou": ""
                }
            ]
        }
    }
}

询问

有人能帮我弄清楚这一点,并解释一些可能的更好的方法?

5q4ezhmt

5q4ezhmt1#

你就差一点就能成功了。我修改了函数,将var_namejson_objvar_schema沿着使用。然后,它可以使用来自var_schema_typevar_name添加到提供的json_obj。如果var_schema中定义了更多的变量,那么它会调用函数来添加每个变量。传递该变量的模式细节以及要添加变量的json_obj
我不熟悉你提到的Cerberus Json模式,所以你可能想在get_default_value函数中添加一些额外的代码。希望enum类型的详细信息在模式中。

def get_default_value(var_schema: dict):
    data_type = var_schema.get('_type', 'dict')
    if data_type == 'string':
        return ''
        # return var_schema.get('_regex', '')  # use this if you want to get the regex as the default value
    elif data_type == 'dict':
        return {}
    elif data_type == 'bool':
        return False
    elif data_type == 'list':
        return []
    elif data_type == 'int':
        return 0
    elif data_type == 'enum':  # this needs extra handling?
        return ''

def recursively_generate_schema_obj(var_schema: dict, var_name=None, json_obj=None):
    """ Add the supplied var_name to the supplied json_obj. The type of variable added is determined by the '_type'
    field in the supplied var_schema.

    Once the variable has been added, find variables in the supplied schema and recursively call this function to
    add any found.

    :param var_name: Name of variable to add to supplied json_obj
    :param var_schema: Schema with details of variables to add below this variable
    :param json_obj: The json object to add the variable to. This can be a dict or a list. If it's a list, then the
    supplied var_name is not used and an item of type defined in the var_schema is simply appended to the list
    :return: The json_obj
    """
    if isinstance(var_schema, dict):

        next_level = get_default_value(var_schema)
        if json_obj is None:
            json_obj = next_level
        elif isinstance(json_obj, list):
            json_obj.append(next_level)
        else:
            json_obj[var_name] = next_level

        # Find each sub field in the schema and add it to the next level
        # These are keys without an '_' or, for the items to add to a list the '_item_schema'.
        for key, value in var_schema.items():
            if not str(key).startswith("_") or key == '_item_schema':
                recursively_generate_schema_obj(value, key, next_level)

    return json_obj

schema_data = {
    'schema': {
        'vars': {
            'forest_config': {
                '_type': 'list',
                '_required': False,
                '_not_empty': False,
                '_item_schema': {
                    '_type': 'dict',
                    'always_create_dl_here': {'_required': False, '_type': 'bool'},
                    'ldap_domain': {'_type': 'string', '_required': False},
                    'dc_dn': {'_type': 'string', '_required': True, '_not_empty': True,
                              '_regex': '^(DC|O)=[\\w\\-\\. &]+(,(DC|O)=[\\w\\-\\. &]+)*$'},
                    'user_ou': {'_type': 'string','_required': True,'_not_empty': False,
                                '_regex': '^((CN|OU)=[\\w\\-\\. &]+(,(CN|OU)=[\\w\\-\\. &]+)*)?$'},
                    'group_ou': {'_type': 'string', '_required': True, '_not_empty': False,
                                 '_regex': '^((CN|OU)=[\\w\\-\\. &]+(,(CN|OU)=[\\w\\-\\. &]+)*)?$'},
                    'dl_group_ou': {'_type': 'string', '_required': True, '_not_empty': False,
                                    '_regex': '^((CN|OU)=[\\w\\-\\. &]+(,(CN|OU)=[\\w\\-\\. &]+)*)?$'}
                }
            }
        }
    }
}

new_obj = recursively_generate_schema_obj(schema_data)
print(new_obj)

字符串
上面的代码产生:

{
    'schema': {
        'vars': {
            'forest_config': [{
                'always_create_dl_here': False, 
                'ldap_domain': '', 
                'dc_dn': '', 
                'user_ou': '', 
                'group_ou': '', 
                'dl_group_ou': ''
            }]
        }
    }
}

相关问题