-
Notifications
You must be signed in to change notification settings - Fork 109
Description
Is your feature request related to a problem? Please describe.
At first glance I thought Analytics.track(name:properties:) could take any Codable type in the properties dictionary since everything is eventually encoded to JSON, but after closer inspection I discovered that isn't the case sine you use a custom JSON enum that only handles a subset of what can be encoded to JSON.
Here is a place in our code where that assumption is visible:
// If the value is Codable then leave it as is and let Segment encode it into JSON, otherwise make use of CustomStringConvertible
let loggingValue: Any = value as? Codable ?? value.description
analytics.track(name: segmentEvent, properties: ["value": loggingValue])Here I am checking if the value we want to log is Codable and if it is that gets sent as is, and if it isn't then get a string description to send instead. That way the value can be sent with as much information as possible when it is Codable.
Problem is this leads to a crash in DEBUG builds when value is Codable but isn't handled by the JSON enum (like Set).
Describe the solution you'd like
I don't know the history of why a JSON enum is used instead of Codable (or just Encodable) and JSONEncoder, but if it is possible to update Analytics.track(name:properties:) to use [String: Encodable] instead of [String: Any] and then use JSONEncoder to encode the dictionary I think that would be the simplest, and would provide the strongest compile time guarantees.
A change like that would be disruptive enough to warrant waiting 2.0, but I'd love to see it earlier, so perhaps the old can be kept and marked deprecated in 1.4 and then removed in 2.0.
Describe alternatives you've considered
If you can't use the standard JSONEncoder for some reason, then a custom protocol can be used instead of Encodable in place of Any and extend the supported types in JSON with that protocol. Something like SegmentSerializable.
public func track(name: String, properties: [String: SegmentSerializable]? = nil)In JSON.swift:
public extension String: SegmentSerializable {}
public extension Array: SegmentSerializable where Element: SegmentSerializable {}
etc...Additional context
The Encodable solution would be fit in with the Swift ecosystem, as it would allow us to send anything we want to Segment by making it Encodable, and give us compile time assurance that what we are sending will make it to Segment.
If that is deemed impossible for reasons I can't see from the outside I will accept the alternative where at the very least we get compile time assurances.