I have a custom object stored in a Struct:
struct Event {
let type: String
let value: String
let time: Int
}
where time is a UnixTime in millis. In the App I have a scrollable text field when I print this event in json format
{
"type" : "rain",
"value" : "0.5",
"time" : 1681663944
}
but for time parameter I would like to convert the UnixTime in a human readable form (i.e. 16/04/2023), so I need to customize haw this parameter is encoded. The problem is that all my objects are conforms to this protocol, so I have the toJsonString() method for free, based on the power of Codable.
protocol BaseObject: Codable {
}
extension BaseObject {
func toJsonString() -> String {
let jsonEncoder = JSONEncoder()
do {
let jsonData = try jsonEncoder.encode(self)
let json = String(data: jsonData, encoding: String.Encoding.utf8)
return json ?? ""
} catch {
return ""
}
}
}
So, I don't have a toJsonString() method for each object separately. Naïve solution should be write a custom toJsonString() for each object, but I have a lot of struct and if I found a smart way to intercept time attributes I can override the encode representation of all attributes in the App with this type.
Ideas ?
Thanks.
EDIT
For now I found this solution:
func toJsonString() -> String {
let jsonEncoder = JSONEncoder()
do {
let jsonData = try jsonEncoder.encode(self)
var modData = Data()
if var dict = jsonData.toDictionary() {
dict.keys.filter{ $0.contains("time") }.forEach { key in
if let t = dict[key] as? Int {
dict[key] = t.toStringDate()
}
}
modData = dict.toData()
}
let json = String(data: modData, encoding: String.Encoding.utf8)
return json ?? ""
} catch {
return ""
}
}
You can use a property wrapper to hook in and give custom encoding behaviour for a specific property:
Here's an example usage:
Which prints:
This relies on
timeto be aDate(which it probably should be). If it must stay anInt(though I'd caution against that), you can tweak the property wrapper to change the current behaviour (String -> Date,Date -> String) to add an extra processing step (String -> Date -> Int,Int -> Date -> String).