Preserve YAML string types and explicit numeric evidence

This commit is contained in:
2026-11-07 12:06:50 +00:00
parent d7a85f5f35
commit 3223b5cb82
3 changed files with 58 additions and 21 deletions

View File

@@ -33,7 +33,8 @@ func normalizeReport(value any) (any, error) {
// DecodeYAMLReport decodes one YAML document from safe inspection output into
// JSON-compatible values. Unsupported YAML meanings return an error; the result
// is not a lossless representation of the input document.
// is not a lossless representation of the input document. Scalar types follow
// the resolved YAML tags; numeric-looking strings remain strings.
func DecodeYAMLReport(reader io.Reader) (any, error) {
decoder := yaml.NewDecoder(reader)
var doc yaml.Node
@@ -104,18 +105,6 @@ func yamlReportValue(node *yaml.Node, visiting map[*yaml.Node]bool) (any, error)
case yaml.ScalarNode:
switch node.ShortTag() {
case "!!str":
// The YAML resolver falls back to a string when a numeric scalar is
// outside its machine-number range. Preserve explicit and quoted
// strings, but do not silently turn a plain numeric scalar into text.
if node.Style == 0 {
plain := strings.ReplaceAll(node.Value, "_", "")
if yamlInteger.MatchString(plain) {
return yamlReportNumber(node.Value, "!!int")
}
if yamlNumericPlain.MatchString(plain) {
return yamlReportNumber(node.Value, "!!float")
}
}
return node.Value, nil
case "!!null":
return nil, nil
@@ -188,7 +177,14 @@ func reportYAMLNode(value any) (*yaml.Node, error) {
if strings.ContainsAny(string(v), ".eE") {
tag = "!!float"
}
return &yaml.Node{Kind: yaml.ScalarNode, Tag: tag, Value: string(v)}, nil
node := &yaml.Node{Kind: yaml.ScalarNode, Tag: tag, Value: string(v)}
// The YAML emitter can omit numeric tags even when its resolver would
// classify an overflowing token as a string. Retain the numeric evidence
// explicitly; ParseFloat selects only the style, never the stored value.
if _, err := strconv.ParseFloat(string(v), 64); err != nil {
node.Style = yaml.TaggedStyle
}
return node, nil
case []any:
node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
for _, item := range v {