Skip to content

Commit

Permalink
fix: Fix fromJson template function deserializing non-objects
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Dec 1, 2023
1 parent 263205a commit 649c758
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 16 deletions.
20 changes: 8 additions & 12 deletions internal/chezmoi/format.go
Expand Up @@ -107,7 +107,7 @@ func (formatJSON) Name() string {
// Unmarshal implements Format.Unmarshal.
func (formatJSON) Unmarshal(data []byte, value any) error {
switch value := value.(type) {
case *[]any:
case *any, *[]any, *map[string]any:
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.UseNumber()
if err := decoder.Decode(value); err != nil {
Expand All @@ -116,18 +116,14 @@ func (formatJSON) Unmarshal(data []byte, value any) error {
if _, err := decoder.Token(); !errors.Is(err, io.EOF) {
return errExpectedEOF
}
*value = replaceJSONNumbersWithNumericValuesSlice(*value)
return nil
case *map[string]any:
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.UseNumber()
if err := decoder.Decode(value); err != nil {
return err
}
if _, err := decoder.Token(); !errors.Is(err, io.EOF) {
return errExpectedEOF
switch value := value.(type) {
case *any:
*value = replaceJSONNumbersWithNumericValues(*value)
case *[]any:
*value = replaceJSONNumbersWithNumericValuesSlice(*value)
case *map[string]any:
*value = replaceJSONNumbersWithNumericValuesMap(*value)
}
*value = replaceJSONNumbersWithNumericValuesMap(*value)
return nil
default:
return json.Unmarshal(data, value)
Expand Down
8 changes: 4 additions & 4 deletions internal/cmd/templatefuncs.go
Expand Up @@ -180,7 +180,7 @@ func (c *Config) fromIniTemplateFunc(s string) map[string]any {
//
//nolint:revive,stylecheck
func (c *Config) fromJsonTemplateFunc(s string) any {
var value map[string]any
var value any
if err := chezmoi.FormatJSON.Unmarshal([]byte(s), &value); err != nil {
panic(err)
}
Expand All @@ -190,23 +190,23 @@ func (c *Config) fromJsonTemplateFunc(s string) any {
// fromJsoncTemplateFunc parses s as JSONC and returns the result. In contrast
// to encoding/json, numbers are represented as int64s or float64s if possible.
func (c *Config) fromJsoncTemplateFunc(s string) any {
var value map[string]any
var value any
if err := chezmoi.FormatJSONC.Unmarshal([]byte(s), &value); err != nil {
panic(err)
}
return value
}

func (c *Config) fromTomlTemplateFunc(s string) any {
var value map[string]any
var value any
if err := chezmoi.FormatTOML.Unmarshal([]byte(s), &value); err != nil {
panic(err)
}
return value
}

func (c *Config) fromYamlTemplateFunc(s string) any {
var value map[string]any
var value any
if err := chezmoi.FormatYAML.Unmarshal([]byte(s), &value); err != nil {
panic(err)
}
Expand Down
8 changes: 8 additions & 0 deletions internal/cmd/testdata/scripts/templatefuncs.txtar
Expand Up @@ -24,6 +24,14 @@ cmp stdout golden/deleteValueAtPath
exec chezmoi execute-template '{{ eqFold "foo" "Foo" "FOO" }}'
stdout '^true$'

# test that the fromJson template function can deserialize JSON values
exec chezmoi execute-template '{{ fromJson "1" }}'
stdout '^1$'

# test that the fromJson template function can deserialize JSON arrays
exec chezmoi execute-template '{{ fromJson "[1, 2]" }}'
stdout '^\[1 2\]$'

# test fromJsonc template function
stdin golden/example.jsonc
exec chezmoi execute-template --with-stdin '{{ fromJsonc .chezmoi.stdin | toJson }}'
Expand Down

0 comments on commit 649c758

Please sign in to comment.