我应该如何在 YAML 中编写和解组 byte64 编码值
How should I write and unmarshal a byte64 encoded value in YAML
我的 Yaml 文件的一部分
rules:
- action:
count: {}
name: rulenumbertwo
priority: 123
statement:
bytematchstatement:
fieldtomatch:
singleheader:
name: foobar
positionalconstraint: CONTAINS
searchstring: [103, 105, 122, 122, 98, 117, 122, 122]
上面的结果是搜索字符串值对应的 ASCII 字符串(“fizzbuzz”)。但是我怎样才能把它写成人类可读的格式呢? manual 表示应该“自动”转换搜索字符串,但如果我不将其写为 ASCII 码数组,它会抛出错误。
我的代码(试图解组它,如果我直接写数组但它不是人类可读的,它会起作用):
d := &wafv2.UpdateRuleGroupInput{}
err = yaml.Unmarshal(buf, d)
我想简单的写YAML如下
rules:
- action:
count: {}
name: rulenumbertwo
priority: 123
statement:
bytematchstatement:
fieldtomatch:
singleheader:
name: foobar
positionalconstraint: CONTAINS
searchstring: fizzbuzz
或者可能使用模板(但为什么什么时候应该很容易)
searchstring: {{ convertStringToByteArray "fizzbuzz" }}
包含 SearchString 的类型 ByteMatchStatement
没有声明任何自定义从 YAML 加载的方式,因此它无法从 YAML 标量加载 []byte
。您 link 的手册描述了类型的语义,但没有定义数据的存储方式(取决于用例,将 string
的内容存储给用户确实有意义[]byte
) 也不知道如何从 YAML 加载它。通常,(反)序列化往往会暴露有关数据模型的事实,否则这些事实将成为实现细节,这就是您在这里遇到的问题。
简单的解决方法是声明一些 type SearchStringType []byte
,将其用于 SearchString
字段并在那里声明一个自定义 UnmarshalYAML
方法来处理到 []byte
的转换.但是,这在您的代码中是不可能的,因为您无法控制类型。
一种可能的修复方法是预处理 YAML 输入:
type LoadableUpdateRuleGroupInput wafv2.UpdateRuleGroupInput
func (l *LoadableUpdateRuleGroupInput) UnmarshalYAML(n *yaml.Node) error {
preprocSearchString(n)
return n.Decode((*wafv2.UpdateRuleGroupInput)(l))
}
func preprocSearchString(n *yaml.Node) {
switch n.Kind {
case yaml.SequenceNode:
for _, item := range n.Content {
preprocSearchString(item)
}
case yaml.MappingNode:
for i := 0; i < len(n.Content); i += 2 {
if n.Content[i].Kind == yaml.ScalarNode &&
n.Content[i].Value == "searchstring" {
toByteSequence(n.Content[i+1])
} else {
preprocSearchString(n.Content[i+1])
}
}
}
}
func toByteSequence(n *yaml.Node) {
n.Kind = yaml.SequenceNode
raw := []byte(n.Value)
n.Content = make([]*yaml.Node, len(raw))
for i := range raw {
n.Content[i] = &yaml.Node{Kind: yaml.ScalarNode, Value: strconv.Itoa(int(raw[i]))}
}
}
通过在解组时使用这个新的子类型,searchstring
的 YAML 标量值将被转换为您编写的 YAML 序列节点。当您加载 YAML 节点时,它将正确加载到 []byte
:
d := &LoadableUpdateRuleGroupInput{}
err = yaml.Unmarshal(buf, d)
此代码需要 gopkg.in/yaml.v3
,v2
无法让您对解组进行尽可能多的控制。
我的 Yaml 文件的一部分
rules:
- action:
count: {}
name: rulenumbertwo
priority: 123
statement:
bytematchstatement:
fieldtomatch:
singleheader:
name: foobar
positionalconstraint: CONTAINS
searchstring: [103, 105, 122, 122, 98, 117, 122, 122]
上面的结果是搜索字符串值对应的 ASCII 字符串(“fizzbuzz”)。但是我怎样才能把它写成人类可读的格式呢? manual 表示应该“自动”转换搜索字符串,但如果我不将其写为 ASCII 码数组,它会抛出错误。
我的代码(试图解组它,如果我直接写数组但它不是人类可读的,它会起作用):
d := &wafv2.UpdateRuleGroupInput{}
err = yaml.Unmarshal(buf, d)
我想简单的写YAML如下
rules:
- action:
count: {}
name: rulenumbertwo
priority: 123
statement:
bytematchstatement:
fieldtomatch:
singleheader:
name: foobar
positionalconstraint: CONTAINS
searchstring: fizzbuzz
或者可能使用模板(但为什么什么时候应该很容易)
searchstring: {{ convertStringToByteArray "fizzbuzz" }}
包含 SearchString 的类型 ByteMatchStatement
没有声明任何自定义从 YAML 加载的方式,因此它无法从 YAML 标量加载 []byte
。您 link 的手册描述了类型的语义,但没有定义数据的存储方式(取决于用例,将 string
的内容存储给用户确实有意义[]byte
) 也不知道如何从 YAML 加载它。通常,(反)序列化往往会暴露有关数据模型的事实,否则这些事实将成为实现细节,这就是您在这里遇到的问题。
简单的解决方法是声明一些 type SearchStringType []byte
,将其用于 SearchString
字段并在那里声明一个自定义 UnmarshalYAML
方法来处理到 []byte
的转换.但是,这在您的代码中是不可能的,因为您无法控制类型。
一种可能的修复方法是预处理 YAML 输入:
type LoadableUpdateRuleGroupInput wafv2.UpdateRuleGroupInput
func (l *LoadableUpdateRuleGroupInput) UnmarshalYAML(n *yaml.Node) error {
preprocSearchString(n)
return n.Decode((*wafv2.UpdateRuleGroupInput)(l))
}
func preprocSearchString(n *yaml.Node) {
switch n.Kind {
case yaml.SequenceNode:
for _, item := range n.Content {
preprocSearchString(item)
}
case yaml.MappingNode:
for i := 0; i < len(n.Content); i += 2 {
if n.Content[i].Kind == yaml.ScalarNode &&
n.Content[i].Value == "searchstring" {
toByteSequence(n.Content[i+1])
} else {
preprocSearchString(n.Content[i+1])
}
}
}
}
func toByteSequence(n *yaml.Node) {
n.Kind = yaml.SequenceNode
raw := []byte(n.Value)
n.Content = make([]*yaml.Node, len(raw))
for i := range raw {
n.Content[i] = &yaml.Node{Kind: yaml.ScalarNode, Value: strconv.Itoa(int(raw[i]))}
}
}
通过在解组时使用这个新的子类型,searchstring
的 YAML 标量值将被转换为您编写的 YAML 序列节点。当您加载 YAML 节点时,它将正确加载到 []byte
:
d := &LoadableUpdateRuleGroupInput{}
err = yaml.Unmarshal(buf, d)
此代码需要 gopkg.in/yaml.v3
,v2
无法让您对解组进行尽可能多的控制。