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

Use Json compacter in the bidders/params endpoint #3395

Merged
merged 24 commits into from
Feb 28, 2024

Conversation

guscarreon
Copy link
Contributor

To not go back to using the default json library in the bidders/params endpoint, this pull requests modifies the handler function to use of the tidwall/pretty library instead.

AlexBVolcy
AlexBVolcy previously approved these changes Jan 10, 2024
@bsardo
Copy link
Collaborator

bsardo commented Jan 11, 2024

What are your thoughts on using encoding/json#HTMLEscape followed by encoding/json#Compact instead of this new library prior to calling jsonutil.Marshal which uses json-iter under the hood?
The HTMLEscape function will convert certain characters to unicode (e.g. < to /u003c) if that's needed and Compact will remove unnecessary white space.

router/router.go Outdated
@@ -44,6 +44,7 @@ import (
"github.com/julienschmidt/httprouter"
_ "github.com/lib/pq"
"github.com/rs/cors"
"github.com/tidwall/pretty"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, why did you choose the pretty package over the built-in json.Compact?

router/router.go Outdated
@@ -76,12 +77,12 @@ func newJsonDirectoryServer(schemaDirectory string, validator openrtb_ext.Bidder
if !isValid {
glog.Fatalf("Schema exists for an unknown bidder: %s", bidder)
}
data[bidder] = json.RawMessage(validator.Schema(bidderName))
data[bidder] = pretty.Ugly([]byte(validator.Schema(bidderName)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of calling the compact method manually, please add it as an extension registered with json-iter. This will allow all code in PBS to get the benefit without needing to manually make these modifications.

@guscarreon guscarreon marked this pull request as draft January 23, 2024 00:42
@@ -122,6 +123,7 @@ func TestJsonSampleRequests(t *testing.T) {
},
}

jsoniter.RegisterExtension(&jsonutil.RawMessageExtension{})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Need to move this line (and all instances of it) to the start of the app. Might be a good use of the func init(), but that doesn't work for tests so we'll need to do something different there.

func TestSingleJSONTest(t *testing.T) {
jsoniter.RegisterExtension(&jsonutil.RawMessageExtension{})
runJsonBasedTest(t, "sample-requests/valid-whole/exemplary/simple.json", "")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Remove dev test.

func init() {
jsonConfigValidationOff.RegisterExtension(&RawMessageExtension{})
jsonConfigValidationOn.RegisterExtension(&RawMessageExtension{})
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My untested attempt at an init func. Doesn't work for tests, but I think that's what TestMain is for.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a TestMain per every *_test.go file that needs to register the extension

dst := bytes.NewBuffer(make([]byte, 0, len(jsonRawMsg)))
if err := json.Compact(dst, jsonRawMsg); err != nil {
stream.Error = err
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Add a test for the error path.

@guscarreon guscarreon force-pushed the removeSpaceFromBidderParams branch from dcf5e27 to b6b8ba5 Compare February 13, 2024 16:10
@@ -21,6 +23,7 @@ import (

func init() {
rand.Seed(time.Now().UnixNano())
jsoniter.RegisterExtension(&jsonutil.RawMessageExtension{})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to register it for all of the jsoniter library, or can/should it be scoped to the jsonConfigValidationOn and jsonConfigValidationOff configs?

@@ -211,3 +213,44 @@ func tryExtractErrorMessage(err error) string {
func isLikelyDetailedErrorMessage(msg string) bool {
return !strings.HasPrefix(msg, "request.")
}

// RawMessageExtension will call json.Compact() on every json.RawMessage field when getting marshalled.
// All other types will be marshalled as usual
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend removing the "All other types will be marshalled as usual" part. Doesn't seem necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

return nil
}

// jsonRawMessageType is declared here so we don't have to call TypeOfPtr(&json.RawMessage{}).Elem() everytime we encode
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO I don't think this comment is necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

},
},
{
desc: "json.RawMessage is passed to Marshal(), expect inner JSON blob to be line-break-free, tab-free, spaces only found inside strings, and compacted into one line",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test names should be simple, short, and contain no spaces. Characters like - and _ are fine. Please use comments to add more description as needed. Same for other tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

test: func(t *testing.T) {
jsoniter.RegisterExtension(&RawMessageExtension{})
out, err := Marshal(json.RawMessage(formatted))
assert.NoError(t, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error check should be require.NoError so we don't try to. compare a potentially invalid out in the following assertion. Same for the other tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test was modified, no longer asserts for error

jsonRawMsg := *(*[]byte)(ptr)

dst := bytes.NewBuffer(make([]byte, 0, len(jsonRawMsg)))
json.Compact(dst, jsonRawMsg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please handle the error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Corrected

@@ -275,3 +282,22 @@ func TestValidateDefaultAliases(t *testing.T) {
}
}
}

func TestBidderParamsCompactedOutput(t *testing.T) {
expectedPrefix := `{"33across":{"$schema":"http://json-schema.org/draft-04/schema#","title":"33Across Adapter Params","description":"A schema which validates params accepted by the 33Across adapter","type":"object","properties":{"productId":{"type":"string","description":"Product type"},"siteId":{"type":"string","description":"Site Id"},"zoneId":{"type":"string","description":"Zone Id"}},"required":["productId","siteId"]}`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this rely on the real 33across static file? Will this test fail if that bidder makes an update?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I forgot to swap the real file for a proper JSON test file. Modified.

@guscarreon guscarreon marked this pull request as ready for review February 22, 2024 04:38
@bsardo bsardo assigned SyntaxNode and hhhjort and unassigned bsardo and AlexBVolcy Feb 22, 2024
hhhjort
hhhjort previously approved these changes Feb 26, 2024
Copy link
Collaborator

@hhhjort hhhjort left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@SyntaxNode SyntaxNode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick with the json test file. Otherwise looks great.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be a real bidder name? Could we use foo instead? The file name is "appnexus" and integer param is for AAX.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in latest commit

@bsardo bsardo merged commit e8267b8 into master Feb 28, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants