Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,25 @@ func writeJSONScalar(ctx *jsonWriteContext, node *yaml.Node) error {
ctx.write(quoteJSONString(node.Value))
return nil

case "!!int", "!!float":
// Numbers - write as-is
case "!!int":
// Check for invalid JSON number formats (e.g., leading zeros)
// In YAML, "009911" might be parsed as int, but JSON doesn't allow leading zeros
// Treat such values as strings to preserve them correctly
if hasInvalidJSONNumberFormat(node.Value) {
ctx.write(quoteJSONString(node.Value))
return nil
}
ctx.write(node.Value)
return nil

case "!!float":
// Check for invalid JSON number formats (e.g., leading zeros)
// YAML may tag values like "009911" as float, but they're invalid in JSON
// Treat such values as strings to preserve them correctly
if hasInvalidJSONNumberFormat(node.Value) {
ctx.write(quoteJSONString(node.Value))
return nil
}
ctx.write(node.Value)
return nil

Expand All @@ -384,6 +401,31 @@ func writeJSONScalar(ctx *jsonWriteContext, node *yaml.Node) error {
}
}

// hasInvalidJSONNumberFormat checks if a numeric string would be invalid in JSON.
// JSON numbers cannot have leading zeros (except for "0" itself or "0.x" floats).
func hasInvalidJSONNumberFormat(value string) bool {
if len(value) < 2 {
return false
}

// Handle negative numbers
start := 0
if value[0] == '-' || value[0] == '+' {
start = 1
if len(value) < 2 {
return false
}
}

// Check for leading zero followed by more digits (invalid in JSON)
// "0" alone is valid, "0.x" is valid, but "00", "01", "007" etc. are not
if value[start] == '0' && len(value) > start+1 && value[start+1] >= '0' && value[start+1] <= '9' {
return true
}

return false
}

// resolveMergeKeys processes YAML merge keys (<<) and returns content with merged values
func resolveMergeKeys(content []*yaml.Node) []*yaml.Node {
if len(content) == 0 {
Expand Down
47 changes: 47 additions & 0 deletions json/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,53 @@ upperCaseBool: FALSE
`,
indentation: 2,
},
{
name: "integer with leading zeros",
yamlInput: `bankCode: 009911`,
expectedJSON: `{
"bankCode": "009911"
}
`,
indentation: 2,
},
{
name: "multiple integers with leading zeros",
yamlInput: `identifiers:
bankCode: 009911
sortCode: 001234`,
expectedJSON: `{
"identifiers": {
"bankCode": "009911",
"sortCode": "001234"
}
}
`,
indentation: 2,
},
{
name: "integers with leading zeros in array",
yamlInput: `codes: [009911, 001234, 005678]`,
expectedJSON: `{
"codes": ["009911", "001234", "005678"]
}
`,
indentation: 2,
},
{
name: "octal-like integer value",
yamlInput: `value: 0777`,
expectedJSON: `{
"value": "0777"
}
`,
indentation: 2,
},
{
name: "quoted string with leading zeros preserved",
yamlInput: `bankCode: "009911"`,
expectedJSON: `{"bankCode":"009911"}` + "\n",
indentation: 0,
},
}

for _, tt := range tests {
Expand Down
Loading