Skip to content

Commit 45dc335

Browse files
committed
Don't output traits if they are empty.
1 parent 59ae167 commit 45dc335

File tree

5 files changed

+63
-20
lines changed

5 files changed

+63
-20
lines changed

Examples/other_plugins/InjectTraits.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ class InjectTraits: Plugin {
4444
var workingEvent = event
4545

4646
if var context = event?.context?.dictionaryValue {
47-
context[keyPath: "traits"] = analytics?.traits()
47+
if let traits = analytics?.traits() {
48+
context[keyPath: "traits"] = analytics?.traits()
49+
}
4850

4951
workingEvent?.context = try? JSON(context)
5052
}

Package.resolved

Lines changed: 0 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/Segment/Types.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public struct IdentifyEvent: RawEvent {
7070
public var metrics: [JSON]? = nil
7171
public var _metadata: DestinationMetadata? = nil
7272

73-
public var traits: JSON?
73+
@OmitIfNull public var traits: JSON?
7474

7575

7676
public init(userId: String? = nil, traits: JSON? = nil) {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// OmitIfNull.swift
3+
// Segment
4+
//
5+
// Created by Brandon Sneed on 3/11/25.
6+
//
7+
8+
@propertyWrapper
9+
public struct OmitIfNull<T: Codable>: Codable {
10+
public var wrappedValue: T?
11+
12+
public init(wrappedValue: T?) {
13+
self.wrappedValue = wrappedValue
14+
}
15+
16+
public func encode(to encoder: Encoder) throws {
17+
var container = encoder.singleValueContainer()
18+
if let value = wrappedValue {
19+
try container.encode(value)
20+
} else {
21+
try container.encodeNil()
22+
}
23+
}
24+
}
25+
26+
extension KeyedEncodingContainer {
27+
internal mutating func encode<T>(_ value: OmitIfNull<T>, forKey key: Key) throws where T: Encodable {
28+
if value.wrappedValue != nil {
29+
try encode(value.wrappedValue, forKey: key)
30+
}
31+
}
32+
}

Tests/Segment-Tests/Analytics_Tests.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,33 @@ final class Analytics_Tests: XCTestCase {
360360
let traits = identifyEvent?.traits?.dictionaryValue
361361
XCTAssertTrue(traits?["email"] as? String == "blah@blah.com")
362362
}
363+
364+
func testTraitsNull() {
365+
let analytics = Analytics(configuration: Configuration(writeKey: "test"))
366+
let outputReader = OutputReaderPlugin()
367+
analytics.add(plugin: outputReader)
368+
369+
waitUntilStarted(analytics: analytics)
370+
371+
analytics.identify(userId: "brandon", traits: nil)
372+
373+
let identifyEvent: IdentifyEvent? = outputReader.lastEvent as? IdentifyEvent
374+
375+
let encoder = JSONEncoder()
376+
encoder.outputFormatting = .prettyPrinted // Makes the JSON nice and readable
377+
378+
let jsonNoTraits = try! encoder.encode(identifyEvent)
379+
let jsonNoTraitsString = String(data: jsonNoTraits, encoding: .utf8)!
380+
381+
XCTAssertFalse(jsonNoTraitsString.contains("\"traits\""))
382+
383+
analytics.identify(userId: "brandon", traits: ["some": "value"])
384+
let identifyEventTraits: IdentifyEvent? = outputReader.lastEvent as? IdentifyEvent
385+
let jsonWithTraits = try! encoder.encode(identifyEventTraits)
386+
let jsonWithTraitsString = String(data: jsonWithTraits, encoding: .utf8)!
387+
388+
XCTAssertTrue(jsonWithTraitsString.contains("\"traits\""))
389+
}
363390

364391
func testUserIdAndTraitsPersistCorrectly() {
365392
let analytics = Analytics(configuration: Configuration(writeKey: "test"))

0 commit comments

Comments
 (0)