Skip to content

Commit b0d292e

Browse files
committed
add test for PreTransformKeyedDecodingContainer
1 parent e431a25 commit b0d292e

File tree

1 file changed

+279
-8
lines changed

1 file changed

+279
-8
lines changed

Tests/ReerJSONTests/ReerJSONDecoderTests.swift

Lines changed: 279 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -937,16 +937,32 @@ class ReerJSONTests: XCTestCase {
937937
let homeAddress: Address
938938
let workInfo: WorkInfo
939939

940+
// 添加更多可选属性用于测试 decodeIfPresent
941+
let middleName: String?
942+
let alternateEmail: String?
943+
let userScore: Int?
944+
let isPremium: Bool?
945+
let accountBalance: Double?
946+
let lastLoginTime: Float?
947+
let profilePicture: Data?
948+
let websiteUrl: URL?
949+
let birthDate: Date?
950+
940951
struct Address: Codable, Equatable {
941952
let streetName: String
942953
let cityName: String
943954
let zipCode: String
955+
let apartmentNumber: String? // 可选属性
956+
let buildingFloor: Int? // 可选属性
944957
}
945958

946959
struct WorkInfo: Codable, Equatable {
947960
let companyName: String
948961
let jobTitle: String
949962
let startDate: String
963+
let endDate: String? // 可选属性
964+
let monthlySalary: Double? // 可选属性
965+
let isRemote: Bool? // 可选属性
950966
}
951967
}
952968

@@ -961,17 +977,29 @@ class ReerJSONTests: XCTestCase {
961977
"home_address": {
962978
"street_name": "Main St",
963979
"city_name": "New York",
964-
"zip_code": "10001"
980+
"zip_code": "10001",
981+
"apartment_number": "4B",
982+
"building_floor": null
965983
},
966984
"work_info": {
967985
"company_name": "Tech Corp",
968986
"job_title": "Engineer",
969-
"start_date": "2020-01-01"
970-
}
987+
"start_date": "2020-01-01",
988+
"monthly_salary": 8500.50,
989+
"is_remote": true
990+
},
991+
"middle_name": null,
992+
"user_score": 95,
993+
"is_premium": false,
994+
"account_balance": 1250.75,
995+
"last_login_time": 3.14159,
996+
"profile_picture": "SGVsbG8gV29ybGQ=",
997+
"website_url": "https://johndoe.dev",
998+
"birth_date": 631152000
971999
}
9721000
"""
9731001

974-
testRoundTrip(of: SnakeCaseTest.self, json: json, keyDecodingStrategy: .convertFromSnakeCase)
1002+
testRoundTrip(of: SnakeCaseTest.self, json: json, dateDecodingStrategy: .secondsSince1970, dataDecodingStrategy: .base64, keyDecodingStrategy: .convertFromSnakeCase)
9751003
}
9761004

9771005
func testPreTransformKeyedDecodingContainerCustomStrategy() {
@@ -981,11 +1009,29 @@ class ReerJSONTests: XCTestCase {
9811009
let userAge: Int
9821010
let isAdmin: Bool
9831011

1012+
// 添加可选属性测试 decodeIfPresent
1013+
let userNickname: String?
1014+
let userPhone: String?
1015+
let userScore: Int?
1016+
let isVerified: Bool?
1017+
let userRating: Double?
1018+
let lastSeen: Float?
1019+
let avatarData: Data?
1020+
let profileUrl: URL?
1021+
9841022
enum CodingKeys: String, CodingKey {
9851023
case userName = "user_name"
9861024
case userEmail = "user_email"
9871025
case userAge = "user_age"
9881026
case isAdmin = "is_admin"
1027+
case userNickname = "user_nickname"
1028+
case userPhone = "user_phone"
1029+
case userScore = "user_score"
1030+
case isVerified = "is_verified"
1031+
case userRating = "user_rating"
1032+
case lastSeen = "last_seen"
1033+
case avatarData = "avatar_data"
1034+
case profileUrl = "profile_url"
9891035
}
9901036
}
9911037

@@ -994,7 +1040,14 @@ class ReerJSONTests: XCTestCase {
9941040
"USER_NAME": "alice",
9951041
"USER_EMAIL": "alice@example.com",
9961042
"USER_AGE": 25,
997-
"IS_ADMIN": false
1043+
"IS_ADMIN": false,
1044+
"USER_NICKNAME": "Ali",
1045+
"USER_SCORE": 88,
1046+
"IS_VERIFIED": null,
1047+
"USER_RATING": 4.7,
1048+
"LAST_SEEN": 1.23,
1049+
"AVATAR_DATA": "dGVzdCBkYXRh",
1050+
"PROFILE_URL": "https://alice.dev"
9981051
}
9991052
"""
10001053

@@ -1006,7 +1059,7 @@ class ReerJSONTests: XCTestCase {
10061059
return _CodingKey(stringValue: lowerKey)!
10071060
}
10081061

1009-
testRoundTrip(of: CustomKeyTest.self, json: json, keyDecodingStrategy: customStrategy)
1062+
testRoundTrip(of: CustomKeyTest.self, json: json, dataDecodingStrategy: .base64, keyDecodingStrategy: customStrategy)
10101063
}
10111064

10121065
func testPreTransformKeyedDecodingContainerCustomStrategyWithPath() {
@@ -1359,19 +1412,39 @@ class ReerJSONTests: XCTestCase {
13591412
let floatValue: Float
13601413
let doubleValue: Double
13611414

1362-
// Optional types
1415+
// Optional types for decodeIfPresent testing
13631416
let optionalString: String?
13641417
let optionalInt: Int?
13651418
let optionalBool: Bool?
13661419

1420+
// Optional integer types
1421+
let optionalInt8: Int8?
1422+
let optionalInt16: Int16?
1423+
let optionalInt32: Int32?
1424+
let optionalInt64: Int64?
1425+
let optionalUInt: UInt?
1426+
let optionalUInt8: UInt8?
1427+
let optionalUInt16: UInt16?
1428+
let optionalUInt32: UInt32?
1429+
let optionalUInt64: UInt64?
1430+
1431+
// Optional floating point types
1432+
let optionalFloat: Float?
1433+
let optionalDouble: Double?
1434+
13671435
// Collections
13681436
let arrayValue: [String]
13691437
let dictionaryValue: [String: Int]
1438+
let optionalArrayValue: [Int]?
1439+
let optionalDictionaryValue: [String: String]?
13701440

13711441
// Special types
13721442
let urlValue: URL
13731443
let dateValue: Date
13741444
let dataValue: Data
1445+
let optionalUrlValue: URL?
1446+
let optionalDateValue: Date?
1447+
let optionalDataValue: Data?
13751448
}
13761449

13771450
let json = """
@@ -1393,14 +1466,30 @@ class ReerJSONTests: XCTestCase {
13931466
"optional_string": "optional_test",
13941467
"optional_int": 123,
13951468
"optional_bool": null,
1469+
"optional_int8": 100,
1470+
"optional_int16": null,
1471+
"optional_int32": 999999,
1472+
"optional_int64": 1234567890123456789,
1473+
"optional_u_int": null,
1474+
"optional_u_int8": 200,
1475+
"optional_u_int16": 50000,
1476+
"optional_u_int32": null,
1477+
"optional_u_int64": 9876543210987654321,
1478+
"optional_float": 2.718,
1479+
"optional_double": null,
13961480
"array_value": ["item1", "item2", "item3"],
13971481
"dictionary_value": {
13981482
"key1": 1,
13991483
"key2": 2
14001484
},
1485+
"optional_array_value": [10, 20, 30],
1486+
"optional_dictionary_value": null,
14011487
"url_value": "https://example.com",
14021488
"date_value": 1609459200,
1403-
"data_value": "SGVsbG8gV29ybGQ="
1489+
"data_value": "SGVsbG8gV29ybGQ=",
1490+
"optional_url_value": "https://optional.example.com",
1491+
"optional_date_value": null,
1492+
"optional_data_value": "T3B0aW9uYWwgRGF0YQ=="
14041493
}
14051494
"""
14061495

@@ -1499,6 +1588,35 @@ class ReerJSONTests: XCTestCase {
14991588
XCTAssertEqual(result.urlValue, URL(string: "https://example.com")!)
15001589
XCTAssertEqual(result.dateValue, Date(timeIntervalSince1970: 1609459200))
15011590
XCTAssertEqual(result.dataValue, "Hello World".data(using: .utf8)!)
1591+
1592+
// Verify optional values from decodeIfPresent
1593+
XCTAssertEqual(result.optionalString, "optional_test")
1594+
XCTAssertEqual(result.optionalInt, 123)
1595+
XCTAssertNil(result.optionalBool)
1596+
1597+
// Verify optional integer types
1598+
XCTAssertEqual(result.optionalInt8, 100)
1599+
XCTAssertNil(result.optionalInt16)
1600+
XCTAssertEqual(result.optionalInt32, 999999)
1601+
XCTAssertEqual(result.optionalInt64, 1234567890123456789)
1602+
XCTAssertNil(result.optionalUInt)
1603+
XCTAssertEqual(result.optionalUInt8, 200)
1604+
XCTAssertEqual(result.optionalUInt16, 50000)
1605+
XCTAssertNil(result.optionalUInt32)
1606+
XCTAssertEqual(result.optionalUInt64, 9876543210987654321)
1607+
1608+
// Verify optional floating point types
1609+
XCTAssertEqual(result.optionalFloat!, 2.718, accuracy: 0.001)
1610+
XCTAssertNil(result.optionalDouble)
1611+
1612+
// Verify optional collections
1613+
XCTAssertEqual(result.optionalArrayValue, [10, 20, 30])
1614+
XCTAssertNil(result.optionalDictionaryValue)
1615+
1616+
// Verify optional special types
1617+
XCTAssertEqual(result.optionalUrlValue, URL(string: "https://optional.example.com")!)
1618+
XCTAssertNil(result.optionalDateValue)
1619+
XCTAssertEqual(result.optionalDataValue, "Optional Data".data(using: .utf8)!)
15021620
}
15031621

15041622
func testPreTransformKeyedDecodingContainerDecodeIfPresent() {
@@ -1538,6 +1656,159 @@ class ReerJSONTests: XCTestCase {
15381656
XCTAssertNil(result.nullInt)
15391657
}
15401658

1659+
func testPreTransformKeyedDecodingContainerDecodeIfPresentEdgeCases() {
1660+
struct EdgeCaseTest: Codable, Equatable {
1661+
// 测试各种整数类型的 decodeIfPresent
1662+
let optInt8Present: Int8?
1663+
let optInt8Null: Int8?
1664+
let optInt8Missing: Int8?
1665+
1666+
let optInt16Present: Int16?
1667+
let optInt16Null: Int16?
1668+
let optInt16Missing: Int16?
1669+
1670+
let optInt32Present: Int32?
1671+
let optInt32Null: Int32?
1672+
let optInt32Missing: Int32?
1673+
1674+
let optInt64Present: Int64?
1675+
let optInt64Null: Int64?
1676+
let optInt64Missing: Int64?
1677+
1678+
let optUIntPresent: UInt?
1679+
let optUIntNull: UInt?
1680+
let optUIntMissing: UInt?
1681+
1682+
let optUInt8Present: UInt8?
1683+
let optUInt8Null: UInt8?
1684+
let optUInt8Missing: UInt8?
1685+
1686+
let optUInt16Present: UInt16?
1687+
let optUInt16Null: UInt16?
1688+
let optUInt16Missing: UInt16?
1689+
1690+
let optUInt32Present: UInt32?
1691+
let optUInt32Null: UInt32?
1692+
let optUInt32Missing: UInt32?
1693+
1694+
let optUInt64Present: UInt64?
1695+
let optUInt64Null: UInt64?
1696+
let optUInt64Missing: UInt64?
1697+
1698+
// 测试浮点类型的 decodeIfPresent
1699+
let optFloatPresent: Float?
1700+
let optFloatNull: Float?
1701+
let optFloatMissing: Float?
1702+
1703+
let optDoublePresent: Double?
1704+
let optDoubleNull: Double?
1705+
let optDoubleMissing: Double?
1706+
1707+
// 测试布尔类型的 decodeIfPresent
1708+
let optBoolPresent: Bool?
1709+
let optBoolNull: Bool?
1710+
let optBoolMissing: Bool?
1711+
1712+
// 测试字符串类型的 decodeIfPresent
1713+
let optStringPresent: String?
1714+
let optStringNull: String?
1715+
let optStringMissing: String?
1716+
}
1717+
1718+
let json = """
1719+
{
1720+
"opt_int8_present": 127,
1721+
"opt_int8_null": null,
1722+
1723+
"opt_int16_present": 32767,
1724+
"opt_int16_null": null,
1725+
1726+
"opt_int32_present": 2147483647,
1727+
"opt_int32_null": null,
1728+
1729+
"opt_int64_present": 9223372036854775807,
1730+
"opt_int64_null": null,
1731+
1732+
"opt_u_int_present": 4294967295,
1733+
"opt_u_int_null": null,
1734+
1735+
"opt_u_int8_present": 255,
1736+
"opt_u_int8_null": null,
1737+
1738+
"opt_u_int16_present": 65535,
1739+
"opt_u_int16_null": null,
1740+
1741+
"opt_u_int32_present": 4294967295,
1742+
"opt_u_int32_null": null,
1743+
1744+
"opt_u_int64_present": 18446744073709551615,
1745+
"opt_u_int64_null": null,
1746+
1747+
"opt_float_present": 3.14159,
1748+
"opt_float_null": null,
1749+
1750+
"opt_double_present": 2.71828182846,
1751+
"opt_double_null": null,
1752+
1753+
"opt_bool_present": true,
1754+
"opt_bool_null": null,
1755+
1756+
"opt_string_present": "hello world",
1757+
"opt_string_null": null
1758+
}
1759+
"""
1760+
1761+
let decoder = ReerJSONDecoder()
1762+
decoder.keyDecodingStrategy = .convertFromSnakeCase
1763+
1764+
let result = try! decoder.decode(EdgeCaseTest.self, from: json.data(using: .utf8)!)
1765+
1766+
// 验证 present 值
1767+
XCTAssertEqual(result.optInt8Present, 127)
1768+
XCTAssertEqual(result.optInt16Present, 32767)
1769+
XCTAssertEqual(result.optInt32Present, 2147483647)
1770+
XCTAssertEqual(result.optInt64Present, 9223372036854775807)
1771+
XCTAssertEqual(result.optUIntPresent, 4294967295)
1772+
XCTAssertEqual(result.optUInt8Present, 255)
1773+
XCTAssertEqual(result.optUInt16Present, 65535)
1774+
XCTAssertEqual(result.optUInt32Present, 4294967295)
1775+
XCTAssertEqual(result.optUInt64Present, 18446744073709551615)
1776+
XCTAssertEqual(result.optFloatPresent!, 3.14159, accuracy: 0.00001)
1777+
XCTAssertEqual(result.optDoublePresent!, 2.71828182846, accuracy: 0.00000000001)
1778+
XCTAssertEqual(result.optBoolPresent, true)
1779+
XCTAssertEqual(result.optStringPresent, "hello world")
1780+
1781+
// 验证 null 值
1782+
XCTAssertNil(result.optInt8Null)
1783+
XCTAssertNil(result.optInt16Null)
1784+
XCTAssertNil(result.optInt32Null)
1785+
XCTAssertNil(result.optInt64Null)
1786+
XCTAssertNil(result.optUIntNull)
1787+
XCTAssertNil(result.optUInt8Null)
1788+
XCTAssertNil(result.optUInt16Null)
1789+
XCTAssertNil(result.optUInt32Null)
1790+
XCTAssertNil(result.optUInt64Null)
1791+
XCTAssertNil(result.optFloatNull)
1792+
XCTAssertNil(result.optDoubleNull)
1793+
XCTAssertNil(result.optBoolNull)
1794+
XCTAssertNil(result.optStringNull)
1795+
1796+
// 验证 missing 值
1797+
XCTAssertNil(result.optInt8Missing)
1798+
XCTAssertNil(result.optInt16Missing)
1799+
XCTAssertNil(result.optInt32Missing)
1800+
XCTAssertNil(result.optInt64Missing)
1801+
XCTAssertNil(result.optUIntMissing)
1802+
XCTAssertNil(result.optUInt8Missing)
1803+
XCTAssertNil(result.optUInt16Missing)
1804+
XCTAssertNil(result.optUInt32Missing)
1805+
XCTAssertNil(result.optUInt64Missing)
1806+
XCTAssertNil(result.optFloatMissing)
1807+
XCTAssertNil(result.optDoubleMissing)
1808+
XCTAssertNil(result.optBoolMissing)
1809+
XCTAssertNil(result.optStringMissing)
1810+
}
1811+
15411812
func testPreTransformKeyedDecodingContainerContains() {
15421813
struct ContainsTest: Codable, Equatable {
15431814
let value: String

0 commit comments

Comments
 (0)