Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix frozeWithCacheReuse #639

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions adapter.go
Expand Up @@ -100,7 +100,7 @@ func (adapter *Decoder) Buffered() io.Reader {
func (adapter *Decoder) UseNumber() {
cfg := adapter.iter.cfg.configBeforeFrozen
cfg.UseNumber = true
adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg.extraExtensions)
adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg)
}

// DisallowUnknownFields causes the Decoder to return an error when the destination
Expand All @@ -109,7 +109,7 @@ func (adapter *Decoder) UseNumber() {
func (adapter *Decoder) DisallowUnknownFields() {
cfg := adapter.iter.cfg.configBeforeFrozen
cfg.DisallowUnknownFields = true
adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg.extraExtensions)
adapter.iter.cfg = cfg.frozeWithCacheReuse(adapter.iter.cfg)
}

// NewEncoder same as json.NewEncoder
Expand All @@ -134,14 +134,14 @@ func (adapter *Encoder) Encode(val interface{}) error {
func (adapter *Encoder) SetIndent(prefix, indent string) {
config := adapter.stream.cfg.configBeforeFrozen
config.IndentionStep = len(indent)
adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg.extraExtensions)
adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg)
}

// SetEscapeHTML escape html by default, set to false to disable
func (adapter *Encoder) SetEscapeHTML(escapeHTML bool) {
config := adapter.stream.cfg.configBeforeFrozen
config.EscapeHTML = escapeHTML
adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg.extraExtensions)
adapter.stream.cfg = config.frozeWithCacheReuse(adapter.stream.cfg)
}

// Valid reports whether data is a valid JSON encoding.
Expand Down
24 changes: 15 additions & 9 deletions config.go
Expand Up @@ -113,16 +113,21 @@ func (cfg *frozenConfig) getEncoderFromCache(cacheKey uintptr) ValEncoder {

var cfgCache = concurrent.NewMap()

func getFrozenConfigFromCache(cfg Config) *frozenConfig {
obj, found := cfgCache.Load(cfg)
type cfgKey struct {
Config
cause *frozenConfig
}

func getFrozenConfigFromCache(key cfgKey) *frozenConfig {
obj, found := cfgCache.Load(key)
if found {
return obj.(*frozenConfig)
}
return nil
}

func addFrozenConfigToCache(cfg Config, frozenConfig *frozenConfig) {
cfgCache.Store(cfg, frozenConfig)
func addFrozenConfigToCache(key cfgKey, frozenConfig *frozenConfig) {
cfgCache.Store(key, frozenConfig)
}

// Froze forge API from config
Expand Down Expand Up @@ -166,16 +171,17 @@ func (cfg Config) Froze() API {
return api
}

func (cfg Config) frozeWithCacheReuse(extraExtensions []Extension) *frozenConfig {
api := getFrozenConfigFromCache(cfg)
func (cfg Config) frozeWithCacheReuse(cause *frozenConfig) *frozenConfig {
key := cfgKey{cfg, cause}
api := getFrozenConfigFromCache(key)
if api != nil {
return api
}
api = cfg.Froze().(*frozenConfig)
for _, extension := range extraExtensions {
for _, extension := range cause.extraExtensions {
api.RegisterExtension(extension)
}
addFrozenConfigToCache(cfg, api)
addFrozenConfigToCache(key, api)
return api
}

Expand Down Expand Up @@ -317,7 +323,7 @@ func (cfg *frozenConfig) MarshalIndent(v interface{}, prefix, indent string) ([]
}
newCfg := cfg.configBeforeFrozen
newCfg.IndentionStep = len(indent)
return newCfg.frozeWithCacheReuse(cfg.extraExtensions).Marshal(v)
return newCfg.frozeWithCacheReuse(cfg).Marshal(v)
}

func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error {
Expand Down
20 changes: 17 additions & 3 deletions extension_tests/extension_test.go
@@ -1,13 +1,14 @@
package test

import (
"github.com/json-iterator/go"
"github.com/modern-go/reflect2"
"github.com/stretchr/testify/require"
"reflect"
"strconv"
"testing"
"unsafe"

jsoniter "github.com/json-iterator/go"
"github.com/modern-go/reflect2"
"github.com/stretchr/testify/require"
)

type TestObject1 struct {
Expand Down Expand Up @@ -59,6 +60,19 @@ func Test_customize_map_key_encoder(t *testing.T) {
m = map[int]int{}
should.NoError(cfg.UnmarshalFromString(output, &m))
should.Equal(map[int]int{1: 2}, m)

b, err := cfg.MarshalIndent(m, "", " ")
should.NoError(err)
should.Equal(`{
"2": 2
}`, string(b))

cfg = jsoniter.Config{}.Froze() // without testMapKeyExtension
b, err = cfg.MarshalIndent(m, "", " ")
should.NoError(err)
should.Equal(`{
"1": 2
}`, string(b))
}

type testMapKeyExtension struct {
Expand Down