May be this way will fit for you, with some modifications. First of all we need keep fields which we want to hash. I keep it in secretFields
. Also we need function for hash like randomString
. And of course we need recursive dynamic decode with HashCodable
.
import Foundation
let jsonData = """{"city":"New York","secret_field": {"first name": "Adam","last name":"Smith"}}"""
// [1]
let secretFIelds = ["first name", "last name"]
// [2]
func randomString(length: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
return String((0..<length).map{ _ in letters.randomElement()! })
}
// [3]
struct HashCodable: Decodable {
var value: Any
struct CodingKeys: CodingKey {
var stringValue: String
var intValue: Int?
init?(intValue: Int) {
self.stringValue = "\(intValue)"
self.intValue = intValue
}
init?(stringValue: String) { self.stringValue = stringValue }
}
init(value: Any) {
self.value = value
}
init(from decoder: Decoder) throws {
if let container = try? decoder.container(keyedBy: CodingKeys.self) {
var result = [String: Any]()
try container.allKeys.forEach { (key) throws in
if secretFIelds.contains(key.stringValue) {
result[key.stringValue] = randomString(length:10)
} else {
result[key.stringValue] =
try container.decode(HashCodable.self, forKey: key).value
}
}
value = result
} else if var container = try? decoder.unkeyedContainer() {
var result = [Any]()
while !container.isAtEnd {
result.append(try container.decode(HashCodable.self).value)
}
value = result
} else if let container = try? decoder.singleValueContainer() {
if let intVal = try? container.decode(Int.self) {
value = intVal
} else if let doubleVal = try? container.decode(Double.self) {
value = doubleVal
} else if let boolVal = try? container.decode(Bool.self) {
value = boolVal
} else if let stringVal = try? container.decode(String.self) {
value = stringVal
} else {
throw DecodingError.dataCorruptedError(
in: container, debugDescription:
"the container contains nothing serialisable")
}
} else {
throw DecodingError.dataCorrupted(
DecodingError.Context(codingPath: decoder.codingPath,
debugDescription: "Could not serialise"))
}
}
}
let decoded = try! JSONDecoder().decode(HashCodable.self, from: jsonData.data(using: .utf8)!)
print(decoded)
input JSON:
{
"city":"New York",
"secret_field": {
"first name": "Adam",
"last name": "Smith"
}
}```
output:
HashCodable(value: [
"city": "New York",
"secret_fields": [
"last name": "3R6ocxYS44",
"first name": "uCFgajZQY7"
]
])```