Support additional unmarshal formats.
- Additional time formats supported - Support for hex format binary string unmarshal - Support for base64 format with prefix - Support for unmarshalling "0" and "1" to boolean value
This commit is contained in:
parent
c93c9f2888
commit
f20bf50879
2 changed files with 70 additions and 11 deletions
7
internal/3rdparty/json/bench_test.go
vendored
7
internal/3rdparty/json/bench_test.go
vendored
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/testenv"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
@ -462,9 +461,9 @@ func BenchmarkUnmapped(b *testing.B) {
|
||||||
func BenchmarkTypeFieldsCache(b *testing.B) {
|
func BenchmarkTypeFieldsCache(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
var maxTypes int = 1e6
|
var maxTypes int = 1e6
|
||||||
if testenv.Builder() != "" {
|
//if testenv.Builder() != "" {
|
||||||
maxTypes = 1e3 // restrict cache sizes on builders
|
// maxTypes = 1e3 // restrict cache sizes on builders
|
||||||
}
|
//}
|
||||||
|
|
||||||
// Dynamically generate many new types.
|
// Dynamically generate many new types.
|
||||||
types := make([]reflect.Type, maxTypes)
|
types := make([]reflect.Type, maxTypes)
|
||||||
|
|
|
||||||
62
internal/3rdparty/json/decode.go
vendored
62
internal/3rdparty/json/decode.go
vendored
|
|
@ -8,12 +8,16 @@
|
||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding"
|
"encoding"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
hex2 "encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/go-jet/jet/v2/internal/utils/datetime"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
@ -851,7 +855,37 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
isNull := item[0] == 'n' // null
|
isNull := item[0] == 'n' // null
|
||||||
u, ut, pv := indirect(v, isNull)
|
u, ut, pv := indirect(v, isNull)
|
||||||
if u != nil {
|
if u != nil {
|
||||||
return u.UnmarshalJSON(item)
|
err := u.UnmarshalJSON(item)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if t, ok := u.(*time.Time); ok {
|
||||||
|
|
||||||
|
if len(item) < 2 || item[0] != '"' || item[len(item)-1] != '"' {
|
||||||
|
d.saveError(fmt.Errorf("Time.UnmarshalJSON: input is not a JSON string"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
item = item[len(`"`) : len(item)-len(`"`)]
|
||||||
|
|
||||||
|
tt, parsed := datetime.TryParseAsTime(item, []string{
|
||||||
|
time.RFC3339Nano,
|
||||||
|
"2006-01-02 15:04:05.999999", // go-sql-driver/mysql
|
||||||
|
"15:04:05-07", // pgx
|
||||||
|
"15:04:05.999999", // pgx
|
||||||
|
})
|
||||||
|
|
||||||
|
if !parsed {
|
||||||
|
d.saveError(fmt.Errorf("json: invalid time, trying to unmarshal %q into %v", item, v.Type()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
*t = tt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
if ut != nil {
|
if ut != nil {
|
||||||
if item[0] != '"' {
|
if item[0] != '"' {
|
||||||
|
|
@ -935,6 +969,21 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
|
d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if bytes.HasPrefix(s, []byte("\\x")) {
|
||||||
|
s = s[2:]
|
||||||
|
b := make([]byte, hex2.DecodedLen(len(s)))
|
||||||
|
n, err := hex2.Decode(b, s)
|
||||||
|
if err != nil {
|
||||||
|
d.saveError(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.SetBytes(b[:n])
|
||||||
|
} else {
|
||||||
|
if bytes.HasPrefix(s, []byte("base64")) {
|
||||||
|
s = s[bytes.LastIndexByte(s, ':')+1:]
|
||||||
|
}
|
||||||
|
|
||||||
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
|
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
|
||||||
n, err := base64.StdEncoding.Decode(b, s)
|
n, err := base64.StdEncoding.Decode(b, s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -942,6 +991,8 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.SetBytes(b[:n])
|
v.SetBytes(b[:n])
|
||||||
|
}
|
||||||
|
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
t := string(s)
|
t := string(s)
|
||||||
if v.Type() == numberType && !isValidNumber(t) {
|
if v.Type() == numberType && !isValidNumber(t) {
|
||||||
|
|
@ -975,6 +1026,15 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
|
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
|
||||||
}
|
}
|
||||||
d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
|
d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
|
||||||
|
case reflect.Bool:
|
||||||
|
itemVal := string(item)
|
||||||
|
|
||||||
|
if itemVal != "1" && itemVal != "0" {
|
||||||
|
d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.SetBool(itemVal == "1")
|
||||||
|
|
||||||
case reflect.Interface:
|
case reflect.Interface:
|
||||||
n, err := d.convertNumber(string(item))
|
n, err := d.convertNumber(string(item))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue