use goccy/go-json to speedup serialization
This commit is contained in:
parent
6013d14bc6
commit
4b4aaf2112
|
@ -5,6 +5,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
// experimental! (need more tests before replacing encoding/json entirely)
|
||||||
|
goccy "github.com/goccy/go-json"
|
||||||
|
|
||||||
"github.com/labstack/echo/v5"
|
"github.com/labstack/echo/v5"
|
||||||
"github.com/pocketbase/pocketbase/tools/search"
|
"github.com/pocketbase/pocketbase/tools/search"
|
||||||
"github.com/pocketbase/pocketbase/tools/tokenizer"
|
"github.com/pocketbase/pocketbase/tools/tokenizer"
|
||||||
|
@ -26,6 +29,9 @@ type Serializer struct {
|
||||||
// Serialize converts an interface into a json and writes it to the response.
|
// Serialize converts an interface into a json and writes it to the response.
|
||||||
//
|
//
|
||||||
// It also provides a generic response data fields picker via the FieldsParam query parameter (default to "fields").
|
// It also provides a generic response data fields picker via the FieldsParam query parameter (default to "fields").
|
||||||
|
//
|
||||||
|
// Note: for the places where it is safe, the std encoding/json is replaced
|
||||||
|
// with goccy due to its slightly better Unmarshal/Marshal performance.
|
||||||
func (s *Serializer) Serialize(c echo.Context, i any, indent string) error {
|
func (s *Serializer) Serialize(c echo.Context, i any, indent string) error {
|
||||||
fieldsParam := s.FieldsParam
|
fieldsParam := s.FieldsParam
|
||||||
if fieldsParam == "" {
|
if fieldsParam == "" {
|
||||||
|
@ -44,15 +50,22 @@ func (s *Serializer) Serialize(c echo.Context, i any, indent string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
encoded, err := json.Marshal(i)
|
// marshalize the provided data to ensure that the related json.Marshaler
|
||||||
|
// implementations are invoked, and then convert it back to a plain
|
||||||
|
// json value that we can further operate on.
|
||||||
|
//
|
||||||
|
// @todo research other approaches to avoid the double serialization
|
||||||
|
// ---
|
||||||
|
encoded, err := json.Marshal(i) // use the std json since goccy has several bugs reported with struct marshaling and it is not safe
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var decoded any
|
var decoded any
|
||||||
if err := json.Unmarshal(encoded, &decoded); err != nil {
|
if err := goccy.Unmarshal(encoded, &decoded); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// ---
|
||||||
|
|
||||||
var isSearchResult bool
|
var isSearchResult bool
|
||||||
switch i.(type) {
|
switch i.(type) {
|
||||||
|
@ -68,7 +81,12 @@ func (s *Serializer) Serialize(c echo.Context, i any, indent string) error {
|
||||||
pickFields(decoded, parsedFields)
|
pickFields(decoded, parsedFields)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.DefaultJSONSerializer.Serialize(c, decoded, indent)
|
enc := goccy.NewEncoder(c.Response())
|
||||||
|
if indent != "" {
|
||||||
|
enc.SetIndent("", indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return enc.Encode(decoded)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFields(rawFields string) (map[string]FieldModifier, error) {
|
func parseFields(rawFields string) (map[string]FieldModifier, error) {
|
||||||
|
|
Loading…
Reference in New Issue