diff --git a/functions/metadata/metadata.go b/functions/metadata/metadata.go index 1a08f392c4f..2d728f209ac 100644 --- a/functions/metadata/metadata.go +++ b/functions/metadata/metadata.go @@ -77,6 +77,24 @@ func (r *Resource) UnmarshalJSON(data []byte) error { return nil } +// MarshalJSON specializes the Resource marshalling to handle the case where the +// value is a string instead of a map. See the comment above on RawPath for why this +// needs to be handled. +func (r *Resource) MarshalJSON() ([]byte, error) { + // If RawPath is set, use that as the whole value. + if r.RawPath != "" { + return []byte(fmt.Sprintf("%q", r.RawPath)), nil + } + + // Otherwise, accept whatever the result of the normal marshal would be. + res := *r + b, err := json.Marshal(res) + if err != nil { + return nil, err + } + return b, nil +} + type contextKey string // GCFContextKey satisfies an interface to be able to use contextKey to read diff --git a/functions/metadata/metadata_test.go b/functions/metadata/metadata_test.go index f6c77f47976..cdfaeb573ff 100644 --- a/functions/metadata/metadata_test.go +++ b/functions/metadata/metadata_test.go @@ -120,3 +120,55 @@ func TestUnmarshalJSON(t *testing.T) { } } } + +func TestMarshalJSON(t *testing.T) { + ts, err := time.Parse("2006-01-02T15:04:05Z07:00", "2019-11-04T23:01:10.112Z") + if err != nil { + t.Fatalf("Error parsing time: %v.", err) + } + var tests = []struct { + name string + metadata Metadata + want []byte + }{ + { + name: "MetadataWithResource", + metadata: Metadata{ + EventID: "1234567", + Timestamp: ts, + EventType: "google.pubsub.topic.publish", + Resource: &Resource{ + Service: "pubsub.googleapis.com", + Name: "mytopic", + Type: "type.googleapis.com/google.pubsub.v1.PubsubMessage", + }, + }, + }, + { + name: "MetadataWithString", + metadata: Metadata{ + EventID: "1234567", + Timestamp: ts, + EventType: "google.pubsub.topic.publish", + Resource: &Resource{ + RawPath: "projects/myproject/mytopic", + }, + }, + }, + } + + for _, tc := range tests { + b, err := json.Marshal(&tc.metadata) + if err != nil { + t.Errorf("MarshalJSON(%s) error: %v", tc.name, err) + } + + var m Metadata + if err := json.Unmarshal(b, &m); err != nil { + t.Errorf("MarshalJSON(%s) error: %v", tc.name, err) + } + if !cmp.Equal(m, tc.metadata) { + t.Errorf("MarshalJSON(%s) error: got %v, want %v", tc.name, m, tc.metadata) + } + } +}