diff --git a/Sources/JWTKit/Claims/LocaleClaim.swift b/Sources/JWTKit/Claims/LocaleClaim.swift index c420bc7d..b7517f50 100644 --- a/Sources/JWTKit/Claims/LocaleClaim.swift +++ b/Sources/JWTKit/Claims/LocaleClaim.swift @@ -12,4 +12,16 @@ public struct LocaleClaim: JWTClaim, Equatable, ExpressibleByStringLiteral { public init(stringLiteral value: String) { self.value = Locale(identifier: value) } + + /// See `Decodable`. + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + try self.init(value: Locale(identifier: container.decode(String.self))) + } + + /// See `Encodable`. + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(value.identifier) + } } diff --git a/Tests/JWTKitTests/JWTKitTests.swift b/Tests/JWTKitTests/JWTKitTests.swift index 18bfb470..9a9b195b 100644 --- a/Tests/JWTKitTests/JWTKitTests.swift +++ b/Tests/JWTKitTests/JWTKitTests.swift @@ -271,6 +271,37 @@ class JWTKitTests: XCTestCase { data = #"{"bad":"Not boolean"}"#.data(using: .utf8)! XCTAssertThrowsError(try JSONDecoder().decode(BoolPayload.self, from: data)) } + + func testLocaleClaim() throws { + let ptBR = #"{"locale":"pt-BR"}"# + + let plainEnglish = try LocalePayload.from(#"{"locale":"en"}"#) + let brazillianPortugese = try LocalePayload.from(ptBR) + let nadizaDialectSlovenia = try LocalePayload.from(#"{"locale":"sl-nedis"}"#) + let germanSwissPost1996 = try LocalePayload.from(#"{"locale":"de-CH-1996"}"#) + let chineseTraditionalTwoPrivate = try LocalePayload.from(#"{"locale":"zh-Hant-CN-x-private1-private2"}"#) + + XCTAssertEqual(plainEnglish.locale.value.identifier, "en") + XCTAssertEqual(brazillianPortugese.locale.value.identifier, "pt-BR") + XCTAssertEqual(nadizaDialectSlovenia.locale.value.identifier, "sl-nedis") + XCTAssertEqual(germanSwissPost1996.locale.value.identifier, "de-CH-1996") + XCTAssertEqual(chineseTraditionalTwoPrivate.locale.value.identifier, "zh-Hant-CN-x-private1-private2") + + let encoded = try JSONEncoder().encode(brazillianPortugese) + let string = String(bytes: encoded, encoding: .utf8)! + XCTAssertEqual(string, ptBR) + } +} + +struct LocalePayload: Codable { + var locale: LocaleClaim +} + +extension LocalePayload { + static func from(_ string: String) throws -> LocalePayload { + let data = string.data(using: .utf8)! + return try JSONDecoder().decode(LocalePayload.self, from: data) + } } struct BoolPayload: Decodable {