From 04daa09e1911d7bdabe87e452200b2de2c5ca7c9 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Feb 2023 15:27:46 -0700 Subject: Be more careful about importing encoding/json --- ReleaseNotes.md | 10 ++++++++++ common.go | 16 ---------------- decode.go | 15 +++------------ encode.go | 9 +-------- external.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 36 deletions(-) delete mode 100644 common.go create mode 100644 external.go diff --git a/ReleaseNotes.md b/ReleaseNotes.md index d1b5693..9974f0e 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,3 +1,13 @@ +# v0.3.6 (TBD) + + Theme: TBD + + User-facing changes: + + - `Number` and `RawMessage` type aliases are now available, so that + a user of lowmemjson's native APIs does not need to import + `encoding/json` or compat/json in order to use them. + # v0.3.5 (2023-02-10) Theme: Compatibility bugfixes diff --git a/common.go b/common.go deleted file mode 100644 index 90156b9..0000000 --- a/common.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (C) 2022-2023 Luke Shumaker -// -// SPDX-License-Identifier: GPL-2.0-or-later - -package lowmemjson - -import ( - "encoding/json" - "reflect" -) - -var ( - numberType = reflect.TypeOf(json.Number("")) - byteType = reflect.TypeOf(byte(0)) - byteSliceType = reflect.TypeOf(([]byte)(nil)) -) diff --git a/decode.go b/decode.go index 1b6bdf2..645f8de 100644 --- a/decode.go +++ b/decode.go @@ -14,7 +14,6 @@ package lowmemjson import ( "bytes" "encoding" - "encoding/json" "fmt" "io" "reflect" @@ -357,14 +356,6 @@ func (dec *Decoder) limitingScanner() io.RuneScanner { // decoder main //////////////////////////////////////////////////////////////////////////////////// -var ( - rawMessagePtrType = reflect.TypeOf((*json.RawMessage)(nil)) - decodableType = reflect.TypeOf((*Decodable)(nil)).Elem() - jsonUnmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem() - textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() - float64Type = reflect.TypeOf(float64(0)) -) - var kind2bits = map[reflect.Kind]int{ reflect.Int: int(32 << (^uint(0) >> 63)), reflect.Int8: 8, @@ -393,7 +384,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { t := dec.peekRuneType() var buf bytes.Buffer dec.scan(&buf) - if err := val.Addr().Interface().(*json.RawMessage).UnmarshalJSON(buf.Bytes()); err != nil { + if err := val.Addr().Interface().(*RawMessage).UnmarshalJSON(buf.Bytes()); err != nil { dec.panicType(t.JSONType(), reflect.PointerTo(typ), err) } case val.CanAddr() && reflect.PointerTo(typ).Implements(decodableType): @@ -410,7 +401,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) { t := dec.peekRuneType() var buf bytes.Buffer dec.scan(&buf) - obj := val.Addr().Interface().(json.Unmarshaler) + obj := val.Addr().Interface().(jsonUnmarshaler) if err := obj.UnmarshalJSON(buf.Bytes()); err != nil { dec.panicType(t.JSONType(), reflect.PointerTo(typ), err) } @@ -826,7 +817,7 @@ func (dec *Decoder) decodeAny() any { case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': var buf strings.Builder dec.scan(&buf) - num := json.Number(buf.String()) + num := Number(buf.String()) if dec.useNumber { return num } diff --git a/encode.go b/encode.go index 492b40f..b6541cd 100644 --- a/encode.go +++ b/encode.go @@ -8,7 +8,6 @@ import ( "bytes" "encoding" "encoding/base64" - "encoding/json" "fmt" "io" "reflect" @@ -96,12 +95,6 @@ func discardInt(_ int, err error) error { return err } -var ( - encodableType = reflect.TypeOf((*Encodable)(nil)).Elem() - jsonMarshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem() - textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() -) - const startDetectingCyclesAfter = 1000 func encode(w *ReEncoder, val reflect.Value, escaper BackslashEscaper, quote bool, cycleDepth uint, cycleSeen map[any]struct{}) error { @@ -145,7 +138,7 @@ func encode(w *ReEncoder, val reflect.Value, escaper BackslashEscaper, quote boo if val.Kind() == reflect.Pointer && val.IsNil() { return discardInt(w.WriteString("null")) } - obj, ok := val.Interface().(json.Marshaler) + obj, ok := val.Interface().(jsonMarshaler) if !ok { return discardInt(w.WriteString("null")) } diff --git a/external.go b/external.go new file mode 100644 index 0000000..c8a1f68 --- /dev/null +++ b/external.go @@ -0,0 +1,48 @@ +// Copyright (C) 2022-2023 Luke Shumaker +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package lowmemjson + +import ( + "encoding" + "encoding/json" + "reflect" +) + +// A Number represents a JSON number value. It is represented as a +// string containing the raw JSON text; it is useful for preserving +// number values with perfect fidelity, but isn't so useful for use as +// a number value in a Go program. +type Number = json.Number + +// A RawMessage is a raw encoded JSON value. This saves time when +// encoding or decoding, but does mean that the full text must be +// buffered when decoding. +type RawMessage = json.RawMessage + +type ( + jsonMarshaler = json.Marshaler + jsonUnmarshaler = json.Unmarshaler +) + +var ( + // common types. + numberType = reflect.TypeOf(Number("")) + byteType = reflect.TypeOf(byte(0)) + byteSliceType = reflect.TypeOf(([]byte)(nil)) + + // encodable/marshaler types. + encodableType = reflect.TypeOf((*Encodable)(nil)).Elem() + jsonMarshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem() + textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() + + // decodable/unmarshaler types. + decodableType = reflect.TypeOf((*Decodable)(nil)).Elem() + jsonUnmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem() + textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() + + // other types used by Decoder. + rawMessagePtrType = reflect.TypeOf((*json.RawMessage)(nil)) + float64Type = reflect.TypeOf(float64(0)) +) -- cgit v1.2.3-2-g168b