Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions openrtb2/banner.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ type Banner struct {
// integer
// Description:
// Indicates if the banner is in the top frame as opposed to an
// iframe, where 0 = no, 1 = yes.
TopFrame int8 `json:"topframe,omitempty"`
// iframe, where 0 = no, 1 = yes, omission indicates Unknown.
TopFrame *int8 `json:"topframe,omitempty"`

// Attribute:
// expdir
Expand Down
7 changes: 4 additions & 3 deletions openrtb2/regs.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ type Regs struct {
// integer
// Description:
// Flag indicating if this request is subject to the COPPA
// regulations established by the USA FTC, where 0 = no, 1 = yes.
// Refer to Section 7.5 for more information.
COPPA int8 `json:"coppa,omitempty"`
// regulations established by the USA FTC, where 0 = no, 1 = yes,
// omission indicates Unknown. Refer to Section 7.5 for more
// information.
COPPA *int8 `json:"coppa,omitempty"`

// Attribute:
// gdpr
Expand Down
5 changes: 3 additions & 2 deletions openrtb2/video.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,9 @@ type Video struct {
// Type:
// integer
// Description:
// Minimum bit rate in Kbps (kilobits per second).
MinBitRate int64 `json:"minbitrate,omitempty"`
// Minimum bit rate in Kbps (kilobits per second). A value of 0 is
// a meaningful floor, distinct from omitting the attribute.
MinBitRate *int64 `json:"minbitrate,omitempty"`

// Attribute:
// maxbitrate
Expand Down
46 changes: 46 additions & 0 deletions openrtb2/zero_value_fields_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package openrtb2_test

import (
"encoding/json"

. "github.com/prebid/openrtb/v20/openrtb2"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

// These fields (Regs.COPPA, Banner.TopFrame, Video.MinBitRate) were previously typed as
// plain int8/int64 with `omitempty`. Because encoding/json's omitempty treats a value type's
// zero value as empty, explicitly setting one of these fields to a meaningful 0 (COPPA: not
// subject to COPPA, TopFrame: not in the top frame, MinBitRate: a real 0 Kbps floor) was
// indistinguishable, once marshaled, from never having set the field at all - the sender's
// explicit signal was silently dropped. See https://github.com/prebid/openrtb/issues/13.
//
// Changing them to pointer types (matching the existing pattern used by Regs.GDPR,
// Banner.Vcm, and Device.DNT for the same "0/1, omission means Unknown" semantics) lets a
// caller distinguish "not set" (nil) from "explicitly set to 0" (Int8Ptr(0)/Int64Ptr(0)).
var _ = Describe("Zero-valued optional fields survive marshaling", func() {
It("keeps Regs.COPPA when explicitly set to 0", func() {
b, err := json.Marshal(Regs{COPPA: Int8Ptr(0)})
Expect(err).NotTo(HaveOccurred())
Expect(b).To(MatchJSON(`{"coppa":0}`))
})

It("omits Regs.COPPA when left unset", func() {
b, err := json.Marshal(Regs{})
Expect(err).NotTo(HaveOccurred())
Expect(b).To(MatchJSON(`{}`))
})

It("keeps Banner.TopFrame when explicitly set to 0", func() {
b, err := json.Marshal(Banner{TopFrame: Int8Ptr(0)})
Expect(err).NotTo(HaveOccurred())
Expect(b).To(MatchJSON(`{"topframe":0}`))
})

It("keeps Video.MinBitRate when explicitly set to 0", func() {
b, err := json.Marshal(Video{MinBitRate: Int64Ptr(0)})
Expect(err).NotTo(HaveOccurred())
Expect(b).To(MatchJSON(`{"mimes":null,"minbitrate":0}`))
})
})