diff --git a/README.md b/README.md index 7b3f88d56..4add4a906 100644 --- a/README.md +++ b/README.md @@ -104,9 +104,13 @@ testify Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell. License (MIT): https://github.com/stretchr/testify/blob/master/LICENSE -json-iterator -Copyright (c) 2016 json-iterator -License (MIT): https://github.com/json-iterator/go/blob/master/LICENSE +go-json +Copyright (c) 2020 go-json +License (MIT): https://github.com/goccy/go-json/blob/master/LICENSE + +go-reflect +Copyright (c) 2020 go-reflect +License (MIT): https://github.com/goccy/go-reflect/blob/master/LICENSE subset Copyright (c) 2015, Facebook, Inc. All rights reserved. diff --git a/go.mod b/go.mod index 86c01349b..cf1714f1f 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,10 @@ module github.com/optimizely/go-sdk go 1.13 require ( + github.com/goccy/go-json v0.10.0 + github.com/goccy/go-reflect v1.2.0 github.com/google/uuid v1.1.1 github.com/hashicorp/go-multierror v1.1.0 - github.com/json-iterator/go v1.1.12 github.com/pkg/errors v0.8.1 github.com/pkg/profile v1.3.0 github.com/stretchr/testify v1.4.0 diff --git a/go.sum b/go.sum index 8c12766bd..904185170 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,15 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= +github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-reflect v1.2.0 h1:O0T8rZCuNmGXewnATuKYnkL0xm6o8UNOJZd/gOkb9ms= +github.com/goccy/go-reflect v1.2.0/go.mod h1:n0oYZn8VcV2CkWTxi8B9QjkCoq6GTtCEdfmR66YhFtE= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.3.0 h1:OQIvuDgm00gWVWGTf4m4mCt6W1/0YqU7Ntg0mySWgaI= @@ -22,7 +18,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/twmb/murmur3 v1.0.0 h1:MLMwMEQRKsu94uJnoveYjjHmcLwI3HNcWXP4LJuNe3I= diff --git a/pkg/client/client.go b/pkg/client/client.go index e695dfaeb..ca91d5f47 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -18,13 +18,15 @@ package client import ( - "encoding/json" "errors" "fmt" - "reflect" "runtime/debug" "strconv" + "github.com/goccy/go-reflect" + + "github.com/goccy/go-json" + "github.com/optimizely/go-sdk/pkg/config" "github.com/optimizely/go-sdk/pkg/decide" "github.com/optimizely/go-sdk/pkg/decision" @@ -1085,5 +1087,5 @@ func (o *OptimizelyClient) getDecisionVariableMap(feature entities.Feature, vari } func isNil(v interface{}) bool { - return v == nil || (reflect.ValueOf(v).Kind() == reflect.Ptr && reflect.ValueOf(v).IsNil()) + return v == nil || (reflect.ValueNoEscapeOf(v).Kind() == reflect.Ptr && reflect.ValueNoEscapeOf(v).IsNil()) } diff --git a/pkg/config/datafileprojectconfig/config_test.go b/pkg/config/datafileprojectconfig/config_test.go index b89e54a9b..3e1d17f1f 100644 --- a/pkg/config/datafileprojectconfig/config_test.go +++ b/pkg/config/datafileprojectconfig/config_test.go @@ -43,7 +43,7 @@ func TestNewDatafileProjectConfigNil(t *testing.T) { func TestNewDatafileProjectConfigNotNil(t *testing.T) { dpc := DatafileProjectConfig{accountID: "123", revision: "1", projectID: "12345", sdkKey: "a", environmentKey: "production", eventMap: map[string]entities.Event{"event_single_targeted_exp": {Key: "event_single_targeted_exp"}}, attributeMap: map[string]entities.Attribute{"10401066170": {ID: "10401066170"}}, integrations: []entities.Integration{{PublicKey: "123", Host: "www.123.com", Key: "odp"}}} - jsonDatafileStr := `{"accountID":"123","revision":"1","projectId":"12345","version":"4","sdkKey":"a","environmentKey":"production","events":[{"key":"event_single_targeted_exp"}],"attributes":[{"id":"10401066170"}],"integrations": [{"publicKey": "123", "host": "www.123.com", "key": "odp"}]}` + jsonDatafileStr := `{"accountId":"123","revision":"1","projectId":"12345","version":"4","sdkKey":"a","environmentKey":"production","events":[{"key":"event_single_targeted_exp"}],"attributes":[{"id":"10401066170"}],"integrations": [{"publicKey": "123", "host": "www.123.com", "key": "odp"}]}` jsonDatafile := []byte(jsonDatafileStr) projectConfig, err := NewDatafileProjectConfig(jsonDatafile, logging.GetLogger("", "DatafileProjectConfig")) assert.Nil(t, err) diff --git a/pkg/config/datafileprojectconfig/entities/entities_test.go b/pkg/config/datafileprojectconfig/entities/entities_test.go index 018f4e8ed..39e6ab810 100644 --- a/pkg/config/datafileprojectconfig/entities/entities_test.go +++ b/pkg/config/datafileprojectconfig/entities/entities_test.go @@ -17,9 +17,10 @@ package entities import ( - "encoding/json" "testing" + "github.com/goccy/go-json" + "github.com/stretchr/testify/assert" ) diff --git a/pkg/config/datafileprojectconfig/json_parser.go b/pkg/config/datafileprojectconfig/json_parser.go index 1df3e33c0..492c915ad 100644 --- a/pkg/config/datafileprojectconfig/json_parser.go +++ b/pkg/config/datafileprojectconfig/json_parser.go @@ -18,13 +18,11 @@ package datafileprojectconfig import ( - "github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig/entities" + "github.com/goccy/go-json" - "github.com/json-iterator/go" + "github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig/entities" ) -var json = jsoniter.ConfigCompatibleWithStandardLibrary - // Parse parses the raw json datafile func Parse(jsonDatafile []byte) (*entities.Datafile, error) { diff --git a/pkg/config/datafileprojectconfig/mappers/condition_trees.go b/pkg/config/datafileprojectconfig/mappers/condition_trees.go index c22df0c3e..6330e8a33 100644 --- a/pkg/config/datafileprojectconfig/mappers/condition_trees.go +++ b/pkg/config/datafileprojectconfig/mappers/condition_trees.go @@ -19,15 +19,16 @@ package mappers import ( "errors" - "reflect" - jsoniter "github.com/json-iterator/go" + "github.com/goccy/go-reflect" + + "github.com/goccy/go-json" + "github.com/optimizely/go-sdk/pkg/decision/evaluator/matchers" "github.com/optimizely/go-sdk/pkg/entities" ) var errEmptyTree = errors.New("empty tree") -var json = jsoniter.ConfigCompatibleWithStandardLibrary // OperatorType defines logical operator for conditions type OperatorType string @@ -47,7 +48,7 @@ func buildConditionTree(conditions interface{}) (conditionTree *entities.TreeNod return } odpSegments = []string{} - value := reflect.ValueOf(parsedConditions) + value := reflect.ValueNoEscapeOf(parsedConditions) visited := make(map[interface{}]bool) conditionTree = &entities.TreeNode{} @@ -150,7 +151,7 @@ func createLeafCondition(typedV map[string]interface{}, node *entities.TreeNode) // Takes the conditions array from the audience in the datafile and turns it into a condition tree func buildAudienceConditionTree(conditions interface{}) (conditionTree *entities.TreeNode, err error) { - value := reflect.ValueOf(conditions) + value := reflect.ValueNoEscapeOf(conditions) visited := make(map[interface{}]bool) conditionTree = &entities.TreeNode{Operator: "or"} diff --git a/pkg/config/datafileprojectconfig/mappers/condition_trees_test.go b/pkg/config/datafileprojectconfig/mappers/condition_trees_test.go index 9bd18ca48..1cef171da 100644 --- a/pkg/config/datafileprojectconfig/mappers/condition_trees_test.go +++ b/pkg/config/datafileprojectconfig/mappers/condition_trees_test.go @@ -19,6 +19,8 @@ package mappers import ( "testing" + "github.com/goccy/go-json" + datafileConfig "github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig/entities" "github.com/optimizely/go-sdk/pkg/entities" "github.com/stretchr/testify/assert" diff --git a/pkg/config/datafileprojectconfig/mappers/events_test.go b/pkg/config/datafileprojectconfig/mappers/events_test.go index 62f5788b4..ca62fbcae 100644 --- a/pkg/config/datafileprojectconfig/mappers/events_test.go +++ b/pkg/config/datafileprojectconfig/mappers/events_test.go @@ -19,6 +19,7 @@ package mappers import ( "testing" + "github.com/goccy/go-json" datafileEntities "github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig/entities" "github.com/optimizely/go-sdk/pkg/entities" "github.com/stretchr/testify/assert" diff --git a/pkg/config/datafileprojectconfig/mappers/experiment_test.go b/pkg/config/datafileprojectconfig/mappers/experiment_test.go index 421c6a96c..da2a67a37 100644 --- a/pkg/config/datafileprojectconfig/mappers/experiment_test.go +++ b/pkg/config/datafileprojectconfig/mappers/experiment_test.go @@ -19,7 +19,8 @@ package mappers import ( "testing" - jsoniter "github.com/json-iterator/go" + "github.com/goccy/go-json" + datafileEntities "github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig/entities" "github.com/optimizely/go-sdk/pkg/entities" "github.com/stretchr/testify/assert" @@ -61,7 +62,6 @@ func TestMapExperiments(t *testing.T) { }` var rawExperiment datafileEntities.Experiment - var json = jsoniter.ConfigCompatibleWithStandardLibrary json.Unmarshal([]byte(testExperimentString), &rawExperiment) rawExperiments := []datafileEntities.Experiment{rawExperiment} diff --git a/pkg/config/datafileprojectconfig/mappers/feature_test.go b/pkg/config/datafileprojectconfig/mappers/feature_test.go index d02eb9341..91ccb5459 100644 --- a/pkg/config/datafileprojectconfig/mappers/feature_test.go +++ b/pkg/config/datafileprojectconfig/mappers/feature_test.go @@ -19,7 +19,8 @@ package mappers import ( "testing" - jsoniter "github.com/json-iterator/go" + "github.com/goccy/go-json" + datafileEntities "github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig/entities" "github.com/optimizely/go-sdk/pkg/entities" "github.com/stretchr/testify/assert" @@ -35,7 +36,6 @@ func TestMapFeatures(t *testing.T) { }` var rawFeatureFlag datafileEntities.FeatureFlag - var json = jsoniter.ConfigCompatibleWithStandardLibrary json.Unmarshal([]byte(testFeatureFlagString), &rawFeatureFlag) rawFeatureFlags := []datafileEntities.FeatureFlag{rawFeatureFlag} diff --git a/pkg/config/datafileprojectconfig/mappers/rollout_test.go b/pkg/config/datafileprojectconfig/mappers/rollout_test.go index 373dcb274..94f2ad9ed 100644 --- a/pkg/config/datafileprojectconfig/mappers/rollout_test.go +++ b/pkg/config/datafileprojectconfig/mappers/rollout_test.go @@ -19,6 +19,8 @@ package mappers import ( "testing" + "github.com/goccy/go-json" + datafileEntities "github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig/entities" "github.com/optimizely/go-sdk/pkg/entities" "github.com/stretchr/testify/assert" diff --git a/pkg/config/optimizely_config.go b/pkg/config/optimizely_config.go index e27a4a702..a03de2f3b 100644 --- a/pkg/config/optimizely_config.go +++ b/pkg/config/optimizely_config.go @@ -18,10 +18,11 @@ package config import ( - "encoding/json" "fmt" "strings" + "github.com/goccy/go-json" + "github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig/mappers" "github.com/optimizely/go-sdk/pkg/entities" ) diff --git a/pkg/config/optimizely_config_test.go b/pkg/config/optimizely_config_test.go index b1341c6b4..ddb18c36b 100644 --- a/pkg/config/optimizely_config_test.go +++ b/pkg/config/optimizely_config_test.go @@ -17,11 +17,13 @@ package config import ( - "encoding/json" "io/ioutil" - "reflect" "testing" + "github.com/goccy/go-reflect" + + "github.com/goccy/go-json" + "github.com/stretchr/testify/suite" ) diff --git a/pkg/decision/evaluator/matchers/utils/to_float.go b/pkg/decision/evaluator/matchers/utils/to_float.go index f61fbabbe..87c36edac 100644 --- a/pkg/decision/evaluator/matchers/utils/to_float.go +++ b/pkg/decision/evaluator/matchers/utils/to_float.go @@ -17,7 +17,7 @@ // Package utils // package utils -import "reflect" +import "github.com/goccy/go-reflect" // ToFloat attempts to convert the given value to a float func ToFloat(value interface{}) (float64, bool) { @@ -26,7 +26,7 @@ func ToFloat(value interface{}) (float64, bool) { return 0, false } var floatType = reflect.TypeOf(float64(0)) - v := reflect.ValueOf(value) + v := reflect.ValueNoEscapeOf(value) v = reflect.Indirect(v) if v.Type().String() == "float64" || v.Type().ConvertibleTo(floatType) { diff --git a/pkg/event/events_test.go b/pkg/event/events_test.go index 1a4eabaa4..c6895ec41 100644 --- a/pkg/event/events_test.go +++ b/pkg/event/events_test.go @@ -18,9 +18,10 @@ package event import ( - "encoding/json" - "github.com/stretchr/testify/assert" "testing" + + "github.com/goccy/go-json" + "github.com/stretchr/testify/assert" ) func TestSnapshotHasOptionalDecisions(t *testing.T) { diff --git a/pkg/odp/event/event_api_manager_test.go b/pkg/odp/event/event_api_manager_test.go index 6cce12309..cc160e53a 100644 --- a/pkg/odp/event/event_api_manager_test.go +++ b/pkg/odp/event/event_api_manager_test.go @@ -18,14 +18,16 @@ package event import ( - "encoding/json" "fmt" "net/http" "net/http/httptest" - "reflect" "testing" "time" + "github.com/goccy/go-reflect" + + "github.com/goccy/go-json" + "github.com/optimizely/go-sdk/pkg/odp/utils" pkgUtils "github.com/optimizely/go-sdk/pkg/utils" "github.com/stretchr/testify/suite" diff --git a/pkg/odp/segment/segment_api_manager.go b/pkg/odp/segment/segment_api_manager.go index 171dc6abd..bff7b7bb6 100644 --- a/pkg/odp/segment/segment_api_manager.go +++ b/pkg/odp/segment/segment_api_manager.go @@ -18,12 +18,13 @@ package segment import ( - "encoding/json" "errors" "fmt" "net/url" "strings" + "github.com/goccy/go-json" + "github.com/optimizely/go-sdk/pkg/logging" "github.com/optimizely/go-sdk/pkg/odp/utils" pkgUtils "github.com/optimizely/go-sdk/pkg/utils" diff --git a/pkg/odp/segment/segment_api_manager_test.go b/pkg/odp/segment/segment_api_manager_test.go index 97b662230..d5be5a845 100644 --- a/pkg/odp/segment/segment_api_manager_test.go +++ b/pkg/odp/segment/segment_api_manager_test.go @@ -22,10 +22,11 @@ import ( "fmt" "net/http" "net/http/httptest" - "reflect" "testing" "time" + "github.com/goccy/go-reflect" + "github.com/optimizely/go-sdk/pkg/logging" "github.com/optimizely/go-sdk/pkg/odp/utils" pkgUtils "github.com/optimizely/go-sdk/pkg/utils" diff --git a/pkg/optimizelyjson/optimizely_json.go b/pkg/optimizelyjson/optimizely_json.go index 143c21560..9fd05bd5d 100644 --- a/pkg/optimizelyjson/optimizely_json.go +++ b/pkg/optimizelyjson/optimizely_json.go @@ -18,10 +18,11 @@ package optimizelyjson import ( - "encoding/json" "errors" "fmt" "strings" + + "github.com/goccy/go-json" ) // OptimizelyJSON holds the underlying structure of the object diff --git a/pkg/utils/requester.go b/pkg/utils/requester.go index 7762960d9..d31cfde8e 100644 --- a/pkg/utils/requester.go +++ b/pkg/utils/requester.go @@ -26,9 +26,9 @@ import ( "net/http" "time" - "github.com/optimizely/go-sdk/pkg/logging" + "github.com/goccy/go-json" - jsoniter "github.com/json-iterator/go" + "github.com/optimizely/go-sdk/pkg/logging" ) const ( @@ -47,8 +47,6 @@ const ( defaultTTL = 5 * time.Second ) -var json = jsoniter.ConfigCompatibleWithStandardLibrary - // Requester is used to make outbound requests with type Requester interface { Get(url string, headers ...Header) (response []byte, responseHeaders http.Header, code int, err error) diff --git a/pkg/utils/types.go b/pkg/utils/types.go index 5e08ddc09..68bb28084 100644 --- a/pkg/utils/types.go +++ b/pkg/utils/types.go @@ -20,7 +20,8 @@ package utils import ( "fmt" "math" - "reflect" + + "github.com/goccy/go-reflect" ) var floatType = reflect.TypeOf(float64(0)) @@ -29,7 +30,7 @@ var intType = reflect.TypeOf(int64(0)) // GetBoolValue will attempt to convert the given value to a bool func GetBoolValue(value interface{}) (bool, error) { if value != nil { - v := reflect.ValueOf(value) + v := reflect.ValueNoEscapeOf(value) if v.Type().String() == "bool" { return v.Bool(), nil } @@ -41,7 +42,7 @@ func GetBoolValue(value interface{}) (bool, error) { // GetFloatValue will attempt to convert the given value to a float64 func GetFloatValue(value interface{}) (float64, error) { if value != nil { - v := reflect.ValueOf(value) + v := reflect.ValueNoEscapeOf(value) v = reflect.Indirect(v) if v.Type().ConvertibleTo(floatType) { fv := v.Convert(floatType) @@ -55,7 +56,7 @@ func GetFloatValue(value interface{}) (float64, error) { // GetIntValue will attempt to convert the given value to an int64 func GetIntValue(value interface{}) (int64, error) { if value != nil { - v := reflect.ValueOf(value) + v := reflect.ValueNoEscapeOf(value) if v.Type().String() == "int64" || v.Type().ConvertibleTo(intType) { intValue := v.Convert(intType).Int() return intValue, nil @@ -68,7 +69,7 @@ func GetIntValue(value interface{}) (int64, error) { // GetStringValue will attempt to convert the given value to a string func GetStringValue(value interface{}) (string, error) { if value != nil { - v := reflect.ValueOf(value) + v := reflect.ValueNoEscapeOf(value) if v.Type().String() == "string" { return v.String(), nil } @@ -107,7 +108,7 @@ func isNumericType(value interface{}) (float64, error) { case float64: return i, nil default: - v := reflect.ValueOf(value) + v := reflect.ValueNoEscapeOf(value) v = reflect.Indirect(v) return math.NaN(), fmt.Errorf("can't convert %v to float64", v.Type()) }