From 6d7db51060d7ad3a4829f09c17cd6d6ffe694c89 Mon Sep 17 00:00:00 2001 From: wibe Date: Fri, 8 Nov 2024 09:03:17 +0100 Subject: [PATCH] This Codable extension for Logger.MetadataValue provides encoding and decoding functionality, mapping MetadataValue cases (string, stringConvertible, dictionary, array) into JSON-compatible formats using the associated type and value keys * Container Encoding: * Each case of MetadataValue is encoded with an explicit type (ValueType) and corresponding value. * stringConvertible is encoded using .description since we need it in a String format. * Container Decoding * When decoding, ValueType is first extracted to determine the case. * For stringConvertible, the String value is decoded and then assigned back to stringConvertible. * Dictionary and array cases are decoded as Logger.Metadata and [Logger.MetadataValue] respectively. --- Sources/Logging/MetadataProvider.swift | 60 ++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/Sources/Logging/MetadataProvider.swift b/Sources/Logging/MetadataProvider.swift index d2daa1a..6ece14e 100644 --- a/Sources/Logging/MetadataProvider.swift +++ b/Sources/Logging/MetadataProvider.swift @@ -99,3 +99,63 @@ extension Logger.MetadataProvider { } } } + + +extension Logger.MetadataValue: Codable { + private enum CodingKeys: String, CodingKey { + case type + case value + } + + private enum ValueType: String, Codable { + case string + case stringConvertible + case dictionary + case array + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + switch self { + case .string(let stringValue): + try container.encode(ValueType.string, forKey: .type) + try container.encode(stringValue, forKey: .value) + + case .stringConvertible(let customValue): + try container.encode(ValueType.stringConvertible, forKey: .type) + try container.encode(customValue.description, forKey: .value) // Encode description + + case .dictionary(let dictValue): + try container.encode(ValueType.dictionary, forKey: .type) + try container.encode(dictValue, forKey: .value) + + case .array(let arrayValue): + try container.encode(ValueType.array, forKey: .type) + try container.encode(arrayValue, forKey: .value) + } + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let type = try container.decode(ValueType.self, forKey: .type) + + switch type { + case .string: + let stringValue = try container.decode(String.self, forKey: .value) + self = .string(stringValue) + + case .stringConvertible: + let stringValue = try container.decode(String.self, forKey: .value) + self = .stringConvertible(stringValue) // Store as `stringConvertible` using `String` type + + case .dictionary: + let dictValue = try container.decode(Logger.Metadata.self, forKey: .value) + self = .dictionary(dictValue) + + case .array: + let arrayValue = try container.decode([Logger.MetadataValue].self, forKey: .value) + self = .array(arrayValue) + } + } +}