generated from amazon-archives/__template_Apache-2.0
-
Notifications
You must be signed in to change notification settings - Fork 71
Open
Description
Description
The JSON encoder's encodeScalar method has a special case for encoding Number values. This case doesn't return so execution continues to encode the value as a string as well.
This causes the same field to be encoded twice, introducing duplicate fields on the JSON object and causing errors when unmarshalling.
Relevant section of the encodeScalar method
smithy-go/document/json/encoder.go
Lines 217 to 230 in 16d913d
| func (e *Encoder) encodeScalar(vp valueProvider, rv reflect.Value) error { | |
| if rv.Type() == serde.ReflectTypeOf.DocumentNumber { | |
| number := rv.Interface().(document.Number) | |
| if !isValidJSONNumber(number.String()) { | |
| return &document.InvalidMarshalError{Message: fmt.Sprintf("invalid number literal: %s", number)} | |
| } | |
| vp.GetValue().Write([]byte(number)) | |
| } | |
| switch rv.Kind() { | |
| case reflect.Bool: | |
| vp.GetValue().Boolean(rv.Bool()) | |
| case reflect.String: | |
| vp.GetValue().String(rv.String()) |
Impact
I have a use-case where I receive and unmarshal a document containing Number values, and then pass that document back to the API again. Unfortunately this issue causes that second API call to error because of the malformed JSON input!
Reproduction
package main
import (
"testing"
smithydocument "github.com/aws/smithy-go/document"
smithydocumentjson "github.com/aws/smithy-go/document/json"
)
func TestEncodeNumber(t *testing.T) {
res, err := smithydocumentjson.NewEncoder().Encode(map[string]interface{}{
// Example of tool call parameters unmarshalled into map[string]interface{}
// Smithy encodes this parameter twice - once as a JSON number and once as a JSON string.
// https://github.com/aws/smithy-go/blob/16d913d93001992645c0f54e3ce9fa6be287b70a/document/json/encoder.go#L217-L230
"x": smithydocument.Number("2"),
})
if err != nil {
t.Fatalf("MarshalSmithyDocument returned error: %v", err)
}
expected := `{"x":2}`
if string(res) != expected {
t.Errorf("Expected JSON output to be %s, got %s", expected, string(res))
}
}Produces:
=== RUN TestEncodeNumber
smithy_test.go:23: Expected JSON output to be {"x":2}, got {"x":2,"x":"2"}
--- FAIL: TestEncodeNumber (0.00s)
FAIL
Metadata
Metadata
Assignees
Labels
No labels