使用golang验证yaml模式(语义检查)

时间:2018-03-23 05:16:38

标签: validation go schema yaml dockerfile

我们有需要阅读具有特定结构的YAML文件的工具。当我们得到YAML文件时,我们需要知道是否

  
      
  1. 根据某些指南 - 语义检查
  2. 检查YAML文件是否有效   
  3. 语法错误(如果有)
  4.   

例如,这是我们需要解决的验证示例

 _version:  {required: true}
   id: {required: true, pattern: '/^[A-Za_\-\.]+$/'}   
   release-version: {required: true}
   type:   

   builds:
     type:seq
     sequence:
       -type:map
     mapping:
        name:{required: true, unique: true, pattern: '/^[A-Za-z0-3_\-\.]+$/'}
        params: 
          type: map
          mapping: { =: {type: any} } 
  

映射是一个关键的值对象
   seq可以有多个构建
  输入任何是和键值

我们使用此开源来解析yaml https://github.com/go-yaml/yaml

一个想法(这是好的)是转换为json,如下所示,通过将文件转换为json并验证它有哪些库来支持它,我的上下文中的任何示例都将非常有用https://github.com/xeipuuv/gojsonschema

但不确定我是如何处理的

Type map
Type seq

2 个答案:

答案 0 :(得分:3)

这是你可以尝试的。

在预期的yaml数据形状之后对结构建模:

type Config struct {
        Version struct {
                Required bool
        }
        ID struct {
                Required bool
                Pattern string
        }
        ReleaseVersion struct {
                Required bool
        }
        Type interface{}
        Builds struct {
                Type []interface{} `yaml:"type"`
                Sequence struct {
                        Type string
                }
                Mapping struct {
                        Name map[string]interface{}
                        Params struct {
                                Type string `yaml:"type"`
                                Mapping struct {
                                        To map[string]string `yaml:"="`
                                }
                        }
                } `yaml:"mapping"`              
        }
}

添加了yaml标志yaml:"somefield",以便为我们感兴趣的数据标记yaml的字段名称。

此外,许多具有未知/未确定类型的字段可以声明为空接口(interface{}),或者如果您想要强制执行"底层表单是一个键值对象,您可以将其声明为map[string]interface{}或另一个结构。

然后我们将yaml数据解组到struct:

cfg := Config{}
err := yaml.Unmarshal([]byte(data), &cfg)
if err != nil {
        log.Fatalf("error: %v", err)
}

由于我们已将字段建模为匿名结构或地图,因此我们可以测试特定字段是否具有"键值"通过检查其与nil的等式来确定值。

// Mapping is a key value object
if (Mapping != nil) {
        // Mapping is a key-value object, since it's not nil.
}


// type any is and key value
// Mapping.To is declared with map[string]string type
// so if it's not nil we can say there's a map there.
if (Mapping.To != nil) {
        // Mapping.To is a map
}

在编组/解编中,地图和结构是可以互换的。结构的好处是你可以提前预定义字段的名称,同时解组到地图,它不会让你清楚键是什么。

答案 1 :(得分:0)

您可以使go-yamljsonschema一起使用。看到此问题:https://github.com/santhosh-tekuri/jsonschema/issues/5

简而言之:

  1. 根据this issue,创建一个可生成兼容输出类型的自定义yaml解析器。
  2. 使用该自定义解析器将Yaml解析为interface{}
  3. jsonschema.ValidateInterface进行验证。

(一旦yaml.v3已发布,则可以使用配置选项替换自定义解组器)

我最初是使用公认的答案的方法来解析为一个结构,然后编写代码以手动验证该结构是否符合我的规范。这很快就变得很丑陋-上述方法允许使用清晰的单独规范并对其进行可靠的验证。