Expected this: name
-> fullname
struct Person: Codable {
let name: String
enum CodingKeys: String, CodingKey {
case name = "fullname"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
}
}
let jsonString = """
{
"name": "John"
}
"""
let jsonDecoder = JSONDecoder()
if let jsonData = jsonString.data(using: .utf8),
let decodedPerson = try? jsonDecoder.decode(Person.self, from: jsonData) {
print(decodedPerson.name) // Output: "John"
}
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .prettyPrinted
if let encodedData = try? jsonEncoder.encode(decodedPerson),
let encodedString = String(data: encodedData, encoding: .utf8) {
print(encodedString)
}
But the reality that second output produce this:
{
"name" : "John"
}
If your goal is to decode the name
key and output the fullname
key (which is really confusing and means your code can't decode the JSON that it generates) then you need to update the CodingKeys
to:
enum CodingKeys: String, CodingKey {
case fullname = "fullname"
case name = "name"
}
and you need to update the encode
method to use .fullname
instead of .name
.
Then you can parse the original JSON with the name
key and then generate new JSON with a fullname
key.
Here's your code with some cleanup and the changes I suggest:
struct Person: Codable {
let name: String
enum CodingKeys: String, CodingKey {
case fullname = "fullname"
case name = "name"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .fullname) // Use fullname
}
}
let jsonString = """
{
"name": "John"
}
"""
do {
let jsonData = jsonString.data(using: .utf8)! // this can't fail
let jsonDecoder = JSONDecoder()
let decodedPerson = try jsonDecoder.decode(Person.self, from: jsonData)
print(decodedPerson.name) // Output: "John"
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .prettyPrinted
let encodedData = try jsonEncoder.encode(decodedPerson)
let encodedString = String(data: encodedData, encoding: .utf8)! // This won't fail either
print(encodedString)
} catch {
print(error)
}
The output is:
John
{
"fullname" : "John"
}
Just to reiterate. This is a bad idea. Your Person
class, with these changes, can't decode the JSON that it encodes. Are you really sure that is what you want?