Skip to content

Commit

Permalink
Enable representing self-describing data using Codable structs (close #…
Browse files Browse the repository at this point in the history
  • Loading branch information
matus-tomlein committed Nov 15, 2023
1 parent f7aadb1 commit 26f665b
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 3 deletions.
13 changes: 13 additions & 0 deletions Sources/Snowplow/Events/SelfDescribing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ public class SelfDescribing: SelfDescribingAbstract {
self._payload = payload
}

/// Creates a self-describing event using data represented as an Encodable struct.
/// - Parameters:
/// - schema: A valid schema URI.
/// - data: Data represented using an Encodable struct.
/// - Returns: A SelfDescribing event.
public convenience init<T: Encodable>(schema: String, data: T) throws {
let data = try JSONEncoder().encode(data)
let jsonObject = try JSONSerialization.jsonObject(with: data)
let dict = jsonObject as! [String: Any]

self.init(schema: schema, payload: dict)
}

private var _schema: String
override var schema: String {
get { return _schema }
Expand Down
13 changes: 13 additions & 0 deletions Sources/Snowplow/Payload/SelfDescribingJson.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,19 @@ public class SelfDescribingJson: NSObject {
public convenience init(schema: String, andSelfDescribingJson data: SelfDescribingJson) {
self.init(schema: schema, andData: data.dictionary)
}

/// Creates a self-describing JSON using data represented as an Encodable struct.
/// - Parameters:
/// - schema: A valid schema URI.
/// - data: Data represented using an Encodable struct.
/// - Returns: A SelfDescribingJson.
public convenience init<T: Encodable>(schema: String, data: T) throws {
let data = try JSONEncoder().encode(data)
let jsonObject = try JSONSerialization.jsonObject(with: data)
let dict = jsonObject as! [String: Any]

self.init(schema: schema, andData: dict)
}

/// Sets the data field of the self-describing JSON.
/// - Parameter data: An SPPayload to be nested into the data.
Expand Down
18 changes: 17 additions & 1 deletion Tests/TestEvents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class TestEvents: XCTestCase {
XCTAssertEqual("action", event.payload["se_ac"] as? String)
}

func testUnstructured() {
func testSelfDescribing() {
var data: [String : Any] = [:]
data["level"] = 23
data["score"] = 56473
Expand All @@ -164,6 +164,22 @@ class TestEvents: XCTestCase {
XCTAssertEqual(23, event.payload["level"] as? Int)
}

func testSelfDescribingWithEncodableData() {
struct Data: Encodable {
var level: Int
var score: Int
}

let data = Data(level: 23, score: 56473)
let event = try? SelfDescribing(
schema: "iglu:com.acme_company/demo_ios_event/jsonschema/1-0-0",
data: data
)
XCTAssertNotNil(event)
XCTAssertEqual("iglu:com.acme_company/demo_ios_event/jsonschema/1-0-0", event?.schema)
XCTAssertEqual(23, event?.payload["level"] as? Int)
}

func testConsentWithdrawn() {
let event = ConsentWithdrawn()
event.name = "name"
Expand Down
36 changes: 34 additions & 2 deletions Tests/TestSelfDescribingJson.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,40 @@ class TestSelfDescribingJson: XCTestCase {
XCTAssertEqual(NSDictionary(dictionary: expected),
NSDictionary(dictionary: sdj.dictionary))
}


func testInitWithEncodable() {
struct EncodableUserData: Encodable {
var firstName: String
var lastName: String
var nickname: String?
var age: Decimal
var children: [EncodableUserData]?
}

let user = EncodableUserData(
firstName: "John",
lastName: "Doe",
age: 32.5,
children: [
EncodableUserData(firstName: "Emily", lastName: "Doe", age: 1.2)
]
)

let json = try? SelfDescribingJson(schema: "iglu:acme.com/user/jsonschema/1-0-0", data: user)
XCTAssertNotNil(json)
XCTAssertEqual(json?.data["firstName"] as? String, "John")
XCTAssertEqual(json?.data["lastName"] as? String, "Doe")
XCTAssertFalse(json?.data.keys.contains("nickname") ?? false)
XCTAssertNotNil(json?.data["children"])
XCTAssertEqual((json?.data["children"] as? Array<Any>)?.count, 1)
XCTAssertEqual(json?.data["age"] as? Double, 32.5)
let children = json?.data["children"] as? Array<Dictionary<String, Any>>
XCTAssertEqual(children?.count, 1)
XCTAssertEqual(children?[0]["firstName"] as? String, "Emily")
XCTAssertEqual(children?[0]["lastName"] as? String, "Doe")
XCTAssertEqual(children?[0]["age"] as? Double, 1.2)
}

func testUpdateSchema() {
let expected: [String : Any] = [
"schema": "iglu:acme.com/test_event_2/jsonschema/1-0-0",
Expand Down Expand Up @@ -161,4 +194,3 @@ class TestSelfDescribingJson: XCTestCase {
NSDictionary(dictionary: sdj.dictionary))
}
}

0 comments on commit 26f665b

Please sign in to comment.