diff --git a/adapter.go b/adapter.go index 92d2cc4a..ba960ae8 100644 --- a/adapter.go +++ b/adapter.go @@ -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 @@ -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 @@ -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. diff --git a/config.go b/config.go index 2adcdc3b..7cd22a4c 100644 --- a/config.go +++ b/config.go @@ -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 @@ -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 } @@ -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 { diff --git a/extension_tests/extension_test.go b/extension_tests/extension_test.go index 836db5bc..26fd9b12 100644 --- a/extension_tests/extension_test.go +++ b/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 { @@ -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 {