如何在Fortran/C混合程序中使用JSON Schema验证YAML?
在Fortran/C混合程序中用JSON Schema验证YAML文件
完全可以在你的Fortran/C混合程序中实现YAML的Schema验证,核心思路是先将YAML转换为JSON结构,再借助成熟的C语言JSON Schema验证库完成校验——因为直接的YAML Schema验证库在C生态中可选较少,而JSON Schema的C库已经非常成熟,且YAML是JSON的超集,大部分结构可以无缝映射。
C端实现步骤
依赖选型
- 保留现有
libyaml用于YAML解析 - 选择C语言JSON库(如
cJSON或jansson)用于构建JSON内存结构 - 选择JSON Schema验证库(如
libjsonschema或jsonschema-validator)完成Schema校验
- 保留现有
具体流程
- 用
libyaml解析YAML文件,生成抽象语法树(AST) - 编写转换逻辑,将YAML AST映射为JSON库对应的内存结构(处理标量、序列、映射等YAML类型到JSON的转换)
- 加载预定义的JSON Schema文件(可编译进程序或运行时读取)
- 调用JSON Schema库验证转换后的JSON结构
- 根据验证结果决定是否继续程序流程:验证失败则输出错误并终止,避免程序挂起
- 用
Fortran端调用方式
Fortran本身没有原生的JSON Schema验证库,可通过bind(c)调用C端封装好的验证函数:
- 在C中封装一个简洁的验证入口函数,接收YAML文件路径和Schema文件路径,返回验证结果码
- 在Fortran中通过
iso_c_binding声明该C函数,在程序启动或读取YAML前调用,根据返回值判断是否继续执行
代码示例
C端验证函数(伪代码)
#include <yaml.h> #include <cjson/cJSON.h> #include <jsonschema.h> // 辅助函数:将YAML节点转换为cJSON对象 cJSON* yaml_node_to_cjson(yaml_node_t* node) { // 实现类型转换逻辑: // - 标量节点转JSON字符串/数字/布尔值 // - 序列节点转JSON数组 // - 映射节点转JSON对象 } int validate_yaml(const char* yaml_file, const char* schema_file) { // 1. 解析YAML文件 yaml_parser_t parser; yaml_parser_initialize(&parser); FILE* f = fopen(yaml_file, "r"); if (!f) return -1; yaml_parser_set_input_file(&parser, f); yaml_document_t doc; if (!yaml_parser_load(&parser, &doc)) { fclose(f); yaml_parser_delete(&parser); return -2; // YAML语法错误 } fclose(f); // 2. 转换YAML到JSON cJSON* json = yaml_node_to_cjson(yaml_document_get_root_node(&doc)); yaml_document_delete(&doc); yaml_parser_delete(&parser); if (!json) return -3; // 转换失败 // 3. 加载Schema cJSON* schema = cJSON_ParseFile(schema_file); if (!schema) { cJSON_Delete(json); return -4; // Schema加载失败 } // 4. 执行Schema验证 jsonschema_error_t error; int result = jsonschema_validate(schema, json, &error); // 清理资源 cJSON_Delete(json); cJSON_Delete(schema); if (result != 0) { fprintf(stderr, "YAML validation failed: %s\n", error.message); jsonschema_error_free(&error); return -5; // 不符合Schema } return 0; // 验证通过 }
Fortran端调用代码
interface function validate_yaml(yaml_path, schema_path) bind(c, name='validate_yaml') use, intrinsic :: iso_c_binding integer(c_int) :: validate_yaml character(kind=c_char), intent(in) :: yaml_path(*) character(kind=c_char), intent(in) :: schema_path(*) end function validate_yaml end interface program yaml_validation_demo use, intrinsic :: iso_c_binding implicit none character(len=256, kind=c_char) :: yaml_file, schema_file integer(c_int) :: status ! 初始化文件路径(需追加C风格空终止符) yaml_file = "config.yaml"//c_null_char schema_file = "config_schema.json"//c_null_char ! 调用C端验证函数 status = validate_yaml(yaml_file, schema_file) if (status /= 0) then print *, "YAML validation failed. Exit code: ", status stop 1 end if ! 验证通过,继续执行后续逻辑 print *, "YAML validation passed. Proceeding..." end program yaml_validation_demo
关键注意事项
- YAML到JSON的转换兼容性:需处理YAML特有的特性(如锚点、别名、多行字符串、自定义标签),确保转换后的JSON能准确反映原YAML的语义,避免出现假阳性的验证错误
- Schema的部署:可将Schema文件编译进程序(如通过二进制资源或硬编码为字符串),减少运行时依赖
- 错误反馈:验证失败时要输出具体错误位置和原因,方便用户修正YAML文件
- 性能平衡:对于大体积YAML文件,转换和验证会带来额外开销,可根据场景选择在程序启动时一次性验证,或分阶段验证关键节点
内容的提问来源于stack exchange,提问作者byrdman1982
相关产品推荐
相关产品推荐

