-
Notifications
You must be signed in to change notification settings - Fork 228
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a hook to specify unmarshal options.
This makes it possible to configure the parser to error out if an unknown tagged field has been found in the byte stream that is being unmarshaled to a go object. NOTE: This change requires go 1.10. It seems that we should all upgrade, see: https://pocketgophers.com/when-should-you-upgrade-go/ For example like this (also see ExampleUnknown in yaml_test.go): ``` func ExampleUnknown() { type WithTaggedField struct { Field string `json:"field"` } y := []byte(`unknown: "hello"`) v := WithTaggedField{} fmt.Printf("%v\n", Unmarshal(y, &v, DisallowUnknownFields)) // Ouptut: // unmarshaling JSON: while decoding JSON: json: unknown field "unknown" } ``` If you want to manipulate the decoder used in the unmarshal function, you can define a custom option to your liking and apply it in the Unmarshal call. The way I found out about this is kind of comical. Some nonprintable characters made their way into my YAML file. You wouldn't see them in the editor, but they'd be there. Now when the YAML file is parsed, the nonprintable chars together with the key characters were made into a weird UTF-8 key (e.g. like "\u00c2some_key"), which would then become a key unknown to the tags of my struct, and would silently get dropped in the parsing steps. So as result, you would get a perfectly normal parse, except the data that you wanted to be in the struct are not there. This meant that silently dropping unknown keys is not always a good idea, so I went to fix it, while retaining the same interface. JSONOpt type was fairly easy to add in the Unmarshal because it can be silently ignored by the old code.
- Loading branch information
Showing
5 changed files
with
88 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
language: go | ||
go: | ||
- 1.3 | ||
- 1.4 | ||
- "1.3" | ||
- "1.4" | ||
- "1.10" | ||
script: | ||
- go test | ||
- go build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// This file contains changes that are only compatible with go 1.10 and onwards. | ||
|
||
// +build go1.10 | ||
|
||
package yaml | ||
|
||
import "encoding/json" | ||
|
||
// DisallowUnknownFields configures the JSON decoder to error out if unknown | ||
// fields come along, instead of dropping them by default. | ||
func DisallowUnknownFields(d *json.Decoder) *json.Decoder { | ||
d.DisallowUnknownFields() | ||
return d | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// +build go1.10 | ||
|
||
package yaml | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
) | ||
|
||
func TestUnmarshalWithTags(t *testing.T) { | ||
type WithTaggedField struct { | ||
Field string `json:"field"` | ||
} | ||
|
||
t.Run("Known tagged field", func(t *testing.T) { | ||
y := []byte(`field: "hello"`) | ||
v := WithTaggedField{} | ||
if err := Unmarshal(y, &v, DisallowUnknownFields); err != nil { | ||
t.Errorf("unexpected error: %v", err) | ||
} | ||
if v.Field != "hello" { | ||
t.Errorf("v.Field=%v, want 'hello'", v.Field) | ||
} | ||
|
||
}) | ||
t.Run("With unknown tagged field", func(t *testing.T) { | ||
y := []byte(`unknown: "hello"`) | ||
v := WithTaggedField{} | ||
err := Unmarshal(y, &v, DisallowUnknownFields) | ||
if err == nil { | ||
t.Errorf("want error because of unknown field, got <nil>: v=%#v", v) | ||
} | ||
}) | ||
|
||
} | ||
|
||
func ExampleUnknown() { | ||
type WithTaggedField struct { | ||
Field string `json:"field"` | ||
} | ||
y := []byte(`unknown: "hello"`) | ||
v := WithTaggedField{} | ||
fmt.Printf("%v\n", Unmarshal(y, &v, DisallowUnknownFields)) | ||
// Ouptut: | ||
// unmarshaling JSON: while decoding JSON: json: unknown field "unknown" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters