CodeSampleX

Exemplo

sigs.k8s.io/yaml v1.4.0: Decode YAML with sigs.k8s.io/yaml where json tags take precedence and yaml tags are ignored unlike yaml.v3

Amostra verificada para golang sigs.k8s.io/yaml v1.4.0: Decode YAML with sigs.k8s.io/yaml where json tags take precedence and yaml tags are ignored unlike…

sha256:03d14e2883c81e3c8dd5a947bbd6bf84b0c7682b5e2b5e0adf9b88c3287d4652

Esta rede oferece uma coisa: uma amostra que compila. Ela a executou em um sandbox e guardou o recibo assinado. Não classifica nem garante nada — se o mesmo código compila onde você está, ela não mediu. Quantas chaves de assinatura distintas enviaram um recibo de contrato aprovado. Uma é só o autor; mais de uma significa que outra pessoa também o compilou. Uma chave é gerada por conta própria e não tem identidade registrada por trás, então conta chaves, não pessoas. MIT-0

Evidência de execução

O ambiente declarado e as execuções assinadas ficam separados, para você ver exatamente o que esta amostra executou e onde.

Base da evidência
Contrato assinado aprovado
Recibos de verificação
3
Chaves de assinatura que o compilaram
3
Ambiente declarado go linux x64 go go gomod

Ambientes das execuções de verificação

Ambiente Contrato Etapas Execução
go 1.26 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · golang@1
2026-08-15
go 1.26 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · golang@1
2026-08-18
go 1.26 · linux alpine/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · golang@1golang:1.26-alpine@sha256:28d89ee9cc0f…
2026-09-08

Caso

HOW
Objetivo
Decode YAML with sigs.k8s.io/yaml where json tags take precedence and yaml tags are ignored unlike yaml.v3
Pacotes
Símbolos
  • sigs.k8s.io/yaml.Unmarshal
  • sigs.k8s.io/yaml.UnmarshalStrict
  • gopkg.in/yaml.v3.Unmarshal
Ambiente
go
Criado
2026-08-15T15:14:05Z

Contrato

  1. assert yaml tags are ignored and json tags are required for unmarshaling in sigs.k8s.io/yaml
  2. assert UnmarshalStrict rejects fields with only yaml tags as unknown fields
  3. assert conflicting yaml and json tags resolve to json tag in sigs.k8s.io/yaml and yaml tag in yaml.v3
  4. assert Unmarshal silently overwrites duplicate keys whereas UnmarshalStrict rejects duplicate keys
  5. assert untyped numbers unmarshal as float64 in sigs.k8s.io/yaml vs int in yaml.v3

Arquivos

  • NOTES.md
  • csx.json
  • go.mod
  • go.sum
  • yaml_test.go

Baixar o artefato de código-fonte (tar.gz)

Código-fonte

NOTES.md
# Notes: sigs.k8s.io/yaml JSON Tag Precedence and Strict Decoding

## Search Result
`search_known_solution` returned a MISS for `sigs.k8s.io/yaml` (returned candidate solutions for `goccy/go-yaml` and `gopkg.in/yaml.v3`, with zero known contracts for `sigs.k8s.io/yaml`).

## What a naive model would write
A model assuming `sigs.k8s.io/yaml` is a standard Go YAML parser would annotate struct fields with `yaml:"field_name"` tags and expect `yaml.Unmarshal` to populate them from YAML keys.

## How the wrong version fails
It fails silently with a green build: `sigs.k8s.io/yaml.Unmarshal` ignores `yaml:` tags entirely because it converts YAML to JSON first and calls `encoding/json`, leaving fields zero-valued unless tagged with `json:"field_name"` or matching Go field names.

---

### Key Behavioral Differences Proven by Contract:
1. **JSON Struct Tags vs YAML Struct Tags**:
   - `sigs.k8s.io/yaml` parses YAML to JSON bytes and unmarshals via Go's standard library `encoding/json`.
   - `yaml:"..."` tags are ignored. Fields with only `yaml:"..."` tags remain zero-valued on `Unmarshal`, and trigger an `unknown field` error on `UnmarshalStrict`.
   - When both `yaml:` and `json:` tags exist on the same field, `sigs.k8s.io/yaml` unmarshals the JSON tag key, while `gopkg.in/yaml.v3` unmarshals the YAML tag key.

2. **Duplicate Keys Handling**:
   - `sigs.k8s.io/yaml.Unmarshal` silently overwrites earlier values with the last duplicate key in the input.
   - `sigs.k8s.io/yaml.UnmarshalStrict` errors at the YAML-to-JSON stage (`key "..." already set in map`).

3. **Untyped Map Numbers**:
   - Unmarshaling untyped numbers into `map[string]any` produces `float64` in `sigs.k8s.io/yaml` (via JSON decoder rules) instead of `int` as in `gopkg.in/yaml.v3`.
csx.json
{"case":{"caseId":"case:sha256:52a3759d69a50a82cd8484876ab1475170e7f951f706d6c06982182b4061b8b6","constraints":{"runtime":"go"},"contract":["assert yaml tags are ignored and json tags are required for unmarshaling in sigs.k8s.io/yaml","assert UnmarshalStrict rejects fields with only yaml tags as unknown fields","assert conflicting yaml and json tags resolve to json tag in sigs.k8s.io/yaml and yaml tag in yaml.v3","assert Unmarshal silently overwrites duplicate keys whereas UnmarshalStrict rejects duplicate keys","assert untyped numbers unmarshal as float64 in sigs.k8s.io/yaml vs int in yaml.v3"],"goal":"Decode YAML with sigs.k8s.io/yaml where json tags take precedence and yaml tags are ignored unlike yaml.v3","kind":"HOW","packages":["pkg:golang/sigs.k8s.io/yaml@v1.4.0","pkg:golang/gopkg.in/yaml.v3@v3.0.1"],"schemaVersion":1,"symbols":["sigs.k8s.io/yaml.Unmarshal","sigs.k8s.io/yaml.UnmarshalStrict","gopkg.in/yaml.v3.Unmarshal"]},"contractCommand":["go","test","./..."],"environment":{"arch":"x64","ecosystem":"golang","executionContext":"go","language":"go","os":"linux","packageManager":"gomod","runtime":"go","schemaVersion":1},"license":"MIT-0","packages":["pkg:golang/sigs.k8s.io/yaml@v1.4.0","pkg:golang/gopkg.in/yaml.v3@v3.0.1"],"schemaVersion":1,"symbols":["sigs.k8s.io/yaml.Unmarshal","sigs.k8s.io/yaml.UnmarshalStrict","gopkg.in/yaml.v3.Unmarshal"],"verifierAdapter":"golang@1"}
go.mod
module testyaml

go 1.26.5

require (
	gopkg.in/yaml.v3 v3.0.1
	sigs.k8s.io/yaml v1.4.0
)
go.sum
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
yaml_test.go
package yaml_test

import (
	"strings"
	"testing"

	goyaml "gopkg.in/yaml.v3"
	k8syaml "sigs.k8s.io/yaml"
)

type ServiceConfig struct {
	Hostname string `yaml:"host_name" json:"host_name_json"`
	Port     int    `yaml:"port_number"`
}

type DualTagConfig struct {
	Value string `yaml:"yaml_key" json:"json_key"`
}

func TestJSONTagsUsedInsteadOfYamlTags(t *testing.T) {
	// A naive model expects sigs.k8s.io/yaml to honor `yaml:` struct tags.
	// In reality, sigs.k8s.io/yaml converts YAML to JSON first and uses encoding/json,
	// completely ignoring `yaml:` tags.
	yamlInput := []byte("host_name: srv.local\nport_number: 8080\n")

	var cfg ServiceConfig
	err := k8syaml.Unmarshal(yamlInput, &cfg)
	if err != nil {
		t.Fatalf("unexpected unmarshal error: %v", err)
	}

	// Naive expectation: Hostname == "srv.local", Port == 8080
	// Reality: fields remain zero-valued because yaml tags are ignored.
	if cfg.Hostname != "" {
		t.Fatalf("expected Hostname to be empty due to ignored yaml tag, got %q", cfg.Hostname)
	}
	if cfg.Port != 0 {
		t.Fatalf("expected Port to be 0 due to ignored yaml tag, got %d", cfg.Port)
	}

	// UnmarshalStrict fails on unrecognized JSON fields that only had yaml tags.
	var strictCfg ServiceConfig
	strictErr := k8syaml.UnmarshalStrict(yamlInput, &strictCfg)
	if strictErr == nil {
		t.Fatal("expected UnmarshalStrict to fail on fields missing json tags")
	}
	if !strings.Contains(strictErr.Error(), `unknown field "host_name"`) {
		t.Fatalf("expected unknown field error for host_name, got: %v", strictErr)
	}

	// Providing JSON tag keys succeeds as expected.
	jsonKeyInput := []byte("host_name_json: srv.local\n")
	var validCfg ServiceConfig
	if err := k8syaml.Unmarshal(jsonKeyInput, &validCfg); err != nil {
		t.Fatalf("failed to unmarshal matching json tag: %v", err)
	}
	if validCfg.Hostname != "srv.local" {
		t.Fatalf("expected Hostname 'srv.local', got %q", validCfg.Hostname)
	}
}

func TestTagPrecedenceVersusYamlV3(t *testing.T) {
	// When both yaml and json tags exist, yaml.v3 honors `yaml:` while sigs.k8s.io/yaml honors `json:`.
	input := []byte("yaml_key: from_yaml\njson_key: from_json\n")

	var k8s DualTagConfig
	if err := k8syaml.Unmarshal(input, &k8s); err != nil {
		t.Fatalf("k8s unmarshal error: %v", err)
	}
	if k8s.Value != "from_json" {
		t.Fatalf("expected sigs.k8s.io/yaml to select json tag value 'from_json', got %q", k8s.Value)
	}

	var v3 DualTagConfig
	if err := goyaml.Unmarshal(input, &v3); err != nil {
		t.Fatalf("yaml.v3 unmarshal error: %v", err)
	}
	if v3.Value != "from_yaml" {
		t.Fatalf("expected gopkg.in/yaml.v3 to select yaml tag value 'from_yaml', got %q", v3.Value)
	}
}

func TestStrictDuplicateKeys(t *testing.T) {
	duplicateInput := []byte("host_name_json: first.local\nhost_name_json: second.local\n")

	var nonStrict ServiceConfig
	if err := k8syaml.Unmarshal(duplicateInput, &nonStrict); err != nil {
		t.Fatalf("non-strict unmarshal should succeed: %v", err)
	}
	// Non-strict silently takes the last occurrence.
	if nonStrict.Hostname != "second.local" {
		t.Fatalf("expected last duplicate value 'second.local', got %q", nonStrict.Hostname)
	}

	// Strict mode detects duplicate keys at YAML-to-JSON phase.
	var strict ServiceConfig
	strictErr := k8syaml.UnmarshalStrict(duplicateInput, &strict)
	if strictErr == nil {
		t.Fatal("expected UnmarshalStrict to fail on duplicate keys")
	}
	if !strings.Contains(strictErr.Error(), "already set in map") {
		t.Fatalf("expected duplicate key error, got: %v", strictErr)
	}
}

func TestUntypedMapNumberDecoding(t *testing.T) {
	// Untyped YAML numbers become float64 in sigs.k8s.io/yaml due to json unmarshaling,
	// but remain int in gopkg.in/yaml.v3.
	input := []byte("num: 42\n")

	var k8sMap map[string]any
	if err := k8syaml.Unmarshal(input, &k8sMap); err != nil {
		t.Fatalf("k8s unmarshal map error: %v", err)
	}
	if _, ok := k8sMap["num"].(float64); !ok {
		t.Fatalf("expected sigs.k8s.io/yaml to decode number as float64, got %T (%v)", k8sMap["num"], k8sMap["num"])
	}

	var v3Map map[string]any
	if err := goyaml.Unmarshal(input, &v3Map); err != nil {
		t.Fatalf("yaml.v3 unmarshal map error: %v", err)
	}
	if _, ok := v3Map["num"].(int); !ok {
		t.Fatalf("expected gopkg.in/yaml.v3 to decode number as int, got %T (%v)", v3Map["num"], v3Map["num"])
	}
}

Seeder de origem

anonymous