You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在非集群环境下验证OpenAPI格式YAML的字段键与值?

解决YAML字段键验证问题(集群外)

核心问题

Go标准库的json.Unmarshal和常用YAML库默认会忽略未知字段,所以用户输入不存在的字段(比如name1代替name)时不会触发错误。要实现字段键的合法性验证,需要开启解析器的"严格模式",让其遇到未知字段时直接返回错误。

方法1:直接用yaml.v3开启严格解析

如果不需要转JSON,直接使用gopkg.in/yaml.v3解析YAML,通过配置解码器开启未知字段检测:

import (
    "bytes"
    "fmt"
    "os"
    "gopkg.in/yaml.v3"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type Test_manifest struct {
    metav1.TypeMeta   `yaml:",inline"`
    metav1.ObjectMeta `yaml:"metadata"`
    Spec              spec `yaml:"spec"`
}

type spec struct {
    Policies  []string  `yaml:"policies"`
    Resources resources `yaml:"resources"`
    Results   []results `yaml:"results"`
    Variables variables `yaml:"variables"`
}

// 需提前定义resources、results、variables结构体

func main() {
    yamlFile, err := os.ReadFile("cmd/cli/kubectl-kyverno/test/test.yaml")
    if err != nil {
        fmt.Printf("Error: failed to read file %v", err)
        return
    }

    var tests Test_manifest
    decoder := yaml.NewDecoder(bytes.NewReader(yamlFile))
    decoder.KnownFields(true) // 开启严格模式,检测未知字段

    if err := decoder.Decode(&tests); err != nil {
        fmt.Printf("Invalid YAML: %v", err)
        return
    }

    // 后续值验证逻辑
    if tests.APIVersion == "" {
        fmt.Println("Error: apiVersion is required")
    }
    if tests.Kind != "KyvernoTest" {
        fmt.Printf("Error: kind must be `KyvernoTest`, got %s", tests.Kind)
    }
}

方法2:转JSON后开启严格解析

如果必须保留转JSON的流程,可使用json.Decoder的DisallowUnknownFields()方法实现字段验证:

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "gopkg.in/yaml.v3"
)

func main() {
    test := "cmd/cli/kubectl-kyverno/test/test.yaml"
    yamlFile, err := ioutil.ReadFile(test)
    if err != nil {
        fmt.Printf("Error: failed to read file %v", err)
        return
    }

    // YAML转JSON
    var rawJSON interface{}
    if err := yaml.Unmarshal(yamlFile, &rawJSON); err != nil {
        fmt.Printf("Failed to parse YAML: %v", err)
        return
    }
    policyBytes, err := json.Marshal(rawJSON)
    if err != nil {
        fmt.Printf("Failed to convert to JSON: %v", err)
        return
    }

    tests := &kyvernov1.Test_manifest{}
    decoder := json.NewDecoder(bytes.NewReader(policyBytes))
    decoder.DisallowUnknownFields() // 禁止解析未知字段

    if err := decoder.Decode(tests); err != nil {
        fmt.Printf("Invalid fields found: %v", err)
        return
    }

    // 后续值验证逻辑
    if tests.TypeMeta.APIVersion == "" {
        fmt.Println("Error: apiVersion not found")
    }
    if tests.TypeMeta.Kind != "KyvernoTest" {
        fmt.Printf("Error: kind is not `KyvernoTest`, got %s", tests.TypeMeta.Kind)
    }
}

关键注意点

  • 确保结构体的字段标签(yaml:"xxx"或json:"xxx")与YAML/JSON字段名完全对应,否则会被误判为未知字段。
  • 对于metav1.TypeMeta这类内嵌结构体,需添加yaml:",inline"标签保证解析正确。
  • 两种方案均无需连接K8s集群,完全在集群外执行验证。

内容的提问来源于stack exchange,提问作者Prateek Nandle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 20:06:22