admin管理员组文章数量:1123649
I'm trying to parse YAML in Go where I have dynamic conditions. Each condition corresponds to a specific struct that implements a common interface. Here's a simplified example of my YAML configuration:
- id: MULTISTAGE01
description: Do not install or keep any compiled programs
stage: final
conditions:
- command.RUN:
cmd: ".*(gcc|nodejs|clang).*"
- id: AVOID01
description: Do not use ADD command
conditions:
- command.ADD:
source: "*"
- id: SECRET01
description: Do not expose secrets
conditions:
- operator.OR:
- command.COPY:
files:
- "*.env"
- command.ENV:
key: "API.*KEY"
Each conditions
entry could represent a FROM
, EXPOSE
, OR
, ADD
, or other type of condition. Each of these is implemented as a separate struct in my Go code, and they all implement a common Condition
interface, which has a Validate()
method.
Here’s an example of the structs and the interface:
type Condition interface {
Validate() error
}
type FROM struct {
BaseCondition
Tag *string `yaml:"tag,omitempty"`
Image *string `yaml:"tag,omitempty"`
}
// Validate implements Condition.
func (from FROM) Validate(stages *[]models.Stage) bool {
result := true
for _, stage := range *stages {
if from.Image != nil {
re, err := regexp.Compile(*from.Image)
if err != nil {
panic(err)
}
result = result && re.Match([]byte(stage.Image.Name))
}
if from.Tag != nil {
re, err := regexp.Compile(*from.Tag)
if err != nil {
panic(err)
}
result = result && re.Match([]byte(stage.Image.Name))
}
}
return result
}
My goal is to unmarshal this YAML into a []Rule
struct, where each Rule
contains a slice of Condition
:
type Rule struct {
Id string `yaml:"id"`
Description string `yaml:"description"`
Conditions []Condition `yaml:"conditions"`
}
The Problem
I'm stuck on how to write the unmarshalling logic for the Conditions
field because I need to dynamically determine which struct (e.g., FORM
, EXPOSE
, etc.) to use based on the key (command.FROM
, stage.EXPOSE
, etc.).
What have i tried
I have tried to use golang inheritage but it didn't work:
type FROM struct {
BaseCondition
Tag *string `yaml:"tag,omitempty"`
Image *string `yaml:"tag,omitempty"`
}
// Validate implements Condition.
func (from FROM) Validate(stages *[]models.Stage) bool {
result := true
for _, stage := range *stages {
if from.Image != nil {
re, err := regexp.Compile(*from.Image)
if err != nil {
panic(err)
}
result = result && re.Match([]byte(stage.Image.Name))
}
if from.Tag != nil {
re, err := regexp.Compile(*from.Tag)
if err != nil {
panic(err)
}
result = result && re.Match([]byte(stage.Image.Name))
}
}
return result
}
How can I implement custom unmarshalling for this YAML structure in Go?
Edit
I tried to implement the UnmarshalYAML method but i keep donc really know what to do next since the types doesn't match
type BaseCondition struct {
Type string `yaml:"-"`
}
type RawCondition map[string]interface{}
func (c *RawCondition) UnmarshalYAML(unmarshal func(interface{}) error) error {
var raw map[string]interface{}
if err := unmarshal(&raw); err != nil {
return err
}
for k, v := range raw {
switch k {
case "command.FROM":
var cond FROM
cond.Type = k
condData, _ := yaml.Marshal(v)
yaml.Unmarshal(condData, &cond)
*c = cond
}
}
return nil
}
本文标签: How to Dynamically Unmarshal YAML into Structs Implementing a Common Interface in GoStack Overflow
版权声明:本文标题:How to Dynamically Unmarshal YAML into Structs Implementing a Common Interface in Go? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736574533a1944824.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论