enabled invalid utf8 character replacement by default for the custom json types

This commit is contained in:
Gani Georgiev
2026-08-24 17:26:36 +03:00
parent 9f4f4d4e73
commit b402f11a79
6 changed files with 28 additions and 10 deletions
+8 -3
View File
@@ -2,6 +2,7 @@ package types
import (
"database/sql/driver"
"encoding/json/jsontext"
"encoding/json/v2"
"fmt"
)
@@ -14,9 +15,13 @@ type jsonArrayAlias[T any] JSONArray[T]
// MarshalJSON implements the [json.Marshaler] interface.
func (m JSONArray[T]) MarshalJSON() ([]byte, error) {
// note: forces the Deterministic option to ensure consistent output
// in mixed json v1 and v2 configurations
return json.Marshal(jsonArrayAlias[T](m), json.Deterministic(true))
// note: forces the Deterministic and AllowInvalidUTF8 options to
// ensure consistent output in mixed json v1 and v2 configurations
return json.Marshal(
jsonArrayAlias[T](m),
json.Deterministic(true),
jsontext.AllowInvalidUTF8(true),
)
}
// String returns the string representation of the current json array.
+1 -1
View File
@@ -18,7 +18,7 @@ func TestJSONArrayMarshalJSON(t *testing.T) {
{types.JSONArray[any]{}, `[]`},
{types.JSONArray[int]{1, 2, 3}, `[1,2,3]`},
{types.JSONArray[string]{"test1", "test2", "test3"}, `["test1","test2","test3"]`},
{types.JSONArray[any]{1, "test"}, `[1,"test"]`},
{types.JSONArray[any]{1, "test\xc3" /* invalid utf8 char to test mangling */}, `[1,"test"]`},
}
for i, s := range scenarios {
+8 -3
View File
@@ -2,6 +2,7 @@ package types
import (
"database/sql/driver"
"encoding/json/jsontext"
"encoding/json/v2"
"fmt"
)
@@ -29,9 +30,13 @@ func (m JSONMap[T]) Set(key string, value T) {
func (m JSONMap[T]) MarshalJSON() ([]byte, error) {
type alias JSONMap[T] // prevent recursion
// note: forces the Deterministic option to ensure consistent output
// in mixed json v1 and v2 configurations
return json.Marshal(alias(m), json.Deterministic(true))
// note: forces the Deterministic and AllowInvalidUTF8 options to
// ensure consistent output in mixed json v1 and v2 configurations
return json.Marshal(
alias(m),
json.Deterministic(true),
jsontext.AllowInvalidUTF8(true),
)
}
// String returns the string representation of the current json map.
+4 -1
View File
@@ -16,8 +16,11 @@ func TestJSONMapMarshalJSON(t *testing.T) {
}{
{nil, "{}"},
{types.JSONMap[any]{}, `{}`},
{types.JSONMap[any]{"test1": 123, "test2": "lorem"}, `{"test1":123,"test2":"lorem"}`},
{types.JSONMap[any]{"test": []int{1, 2, 3}}, `{"test":[1,2,3]}`},
{
types.JSONMap[any]{"test1": 123, "test2": "lorem\xc3" /* invalid utf8 char to test mangling */},
`{"test1":123,"test2":"lorem"}`,
},
}
for i, s := range scenarios {
+2 -1
View File
@@ -2,6 +2,7 @@ package types
import (
"database/sql/driver"
"encoding/json/jsontext"
"encoding/json/v2"
"errors"
)
@@ -73,7 +74,7 @@ func (j *JSONRaw) Scan(value any) error {
data = []byte(v)
}
default:
bytes, err := json.Marshal(v, json.Deterministic(true))
bytes, err := json.Marshal(v, json.Deterministic(true), jsontext.AllowInvalidUTF8(true))
if err != nil {
return err
}
+5 -1
View File
@@ -167,7 +167,11 @@ func TestJSONRawScan(t *testing.T) {
{`{"test":1}`, false, `{"test":1}`},
{[]byte(`[1,2,3]`), false, `[1,2,3]`},
{[]int{1, 2, 3}, false, `[1,2,3]`},
{map[string]int{"test": 1}, false, `{"test":1}`},
{
map[string]string{"test": "a\xc3" /* invalid utf8 char to test mangling */},
false,
`{"test":"a"}`,
},
}
for i, s := range scenarios {