How to decode and get the value in a json

Hi

I want to get the get the value of "name" in the json body after decoding. So far I have managed to get the values of audio and video but not able to get the value of name, Any idea how to get the value?

Sharing a sample of the code

Code Block
import Foundation
let json = """
{
    "from": "Guille",
    "text": "Look what I just found!",
    "attachments": [
        {
            "name": "Test1",
            "type": "image",
            "payload": {
                "url": "url1",
                "width": 640,
                "height": 480
            }
        },
        {
            "name": "Test2",
            "type": "audio",
            "payload": {
                "title": "title1",
                "url": "url2",
                "shouldAutoplay": true,
            }
        },
        {
            "name": "Test3",
            "type": "audio",
            "payload": {
                "title": "title2",
                "url": "url3",
                "shouldAutoplay": true,
            }
        }
    ]
}
""".data(using: .utf8)!
struct ImageAttachment: Codable {
    let url: URL
    let width: Int
    let height: Int
}
struct AudioAttachment: Codable {
    let title: String
    let url: URL
    let shouldAutoplay: Bool
}
enum Attachment {
    case image(ImageAttachment)
    case audio(AudioAttachment)
    case name(String)
    case unsupported
}
extension Attachment: Codable {
    private enum CodingKeys: String, CodingKey {
        case type
        case name
        case payload
    }
    
    enum CodingError: Error {
        case unknownValue
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        let name = try container.decode(String.self, forKey: .name)
        print("decode",name)
        self = .name(name)
        
        let type = try container.decode(String.self, forKey: .type)
        switch type {
        case "image":
            let payload = try container.decode(ImageAttachment.self, forKey: .payload)
            self = .image(payload)
        case "audio":
            let payload = try container.decode(AudioAttachment.self, forKey: .payload)
            self = .audio(payload)
        default:
            self = .unsupported
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        
        switch self {
        case .image(let attachment):
            try container.encode("image", forKey: .type)
            try container.encode(attachment, forKey: .payload)
        case .audio(let attachment):
            try container.encode("audio", forKey: .type)
            try container.encode(attachment, forKey: .payload)
        case .name(let userName):
            try container.encode(userName, forKey: .name)
        case .unsupported:
            let context = EncodingError.Context(codingPath: [], debugDescription: "Invalid attachment.")
            throw EncodingError.invalidValue(self, context)
        }
    }
}
struct Message: Codable {
    let from: String
    let text: String
    let attachments: [Attachment]
}
let decoder = JSONDecoder()
let message = try decoder.decode(Message.self, from: json)
print(message)
for attachment in message.attachments {
    switch attachment {
    case .image(let val):
        print("image", val)
    case .audio(let val):
        print("audio",val)
    case .name(let val):
        print("name", val)
    case .unsupported:
        print("unsupported")
    }
}




Answered by aamirkhan_7 in 661779022
Figured it Out

Hope This Helps

Code Block
import Foundation
let json = """
{
    "from": "Guille",
    "text": "Look what I just found!",
    "attachments": [
        {
            "name": "Test1",
            "type": "image",
            "payload": {
                "url": "url1",
                "width": 640,
                "height": 480
            }
        },
        {
            "name": "Test2",
            "type": "audio",
            "payload": {
                "title": "title1",
                "url": "url2",
                "shouldAutoplay": true,
            }
        },
        {
            "name": "Test3",
            "type": "audio",
            "payload": {
                "title": "title2",
                "url": "url3",
                "shouldAutoplay": true,
            }
        }
    ]
}
""".data(using: .utf8)!
struct ImageAttachment: Codable {
    let url: URL
    let width: Int
    let height: Int
}
struct AudioAttachment: Codable {
    let title: String
    let url: URL
    let shouldAutoplay: Bool
}
struct Test: Codable {
    let name: String
}
enum Attachment {
    case image(String, ImageAttachment)
    case audio(String, AudioAttachment)
    case unsupported
}
extension Attachment: Codable {
    private enum CodingKeys: String, CodingKey {
        case type
        case name
        case payload
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        let name = try container.decode(String.self, forKey: .name)
        
        let type = try container.decode(String.self, forKey: .type)
        switch type {
        case "image":
            let payload = try container.decode(ImageAttachment.self, forKey: .payload)
            self = .image(name, payload)
        case "audio":
            let payload = try container.decode(AudioAttachment.self, forKey: .payload)
            self = .audio(name, payload)
        default:
            self = .unsupported
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        
        switch self {
        case .image(let name, let payload):
            try container.encode("image", forKey: .type)
            try container.encode(payload, forKey: .payload)
            try container.encode(name, forKey: .name)
        case .audio(let name, let payload):
            try container.encode("audio", forKey: .type)
            try container.encode(payload, forKey: .payload)
            try container.encode(name, forKey: .name)
        case .unsupported:
            let context = EncodingError.Context(codingPath: [], debugDescription: "Invalid attachment.")
            throw EncodingError.invalidValue(self, context)
        }
    }
}
struct Message: Codable {
    let from: String
    let text: String
    let attachments: [Attachment]
}
let decoder = JSONDecoder()
let message = try decoder.decode(Message.self, from: json)
for attachment in message.attachments {
    switch attachment {
    case .image(let name, let payload):
        print("image", name)
        print("image", payload)
    case .audio(let name, let payload):
        print("audio",name)
        print("audio", payload)
    case .unsupported:
        print("unsupported")
    }
}


Accepted Answer
Figured it Out

Hope This Helps

Code Block
import Foundation
let json = """
{
    "from": "Guille",
    "text": "Look what I just found!",
    "attachments": [
        {
            "name": "Test1",
            "type": "image",
            "payload": {
                "url": "url1",
                "width": 640,
                "height": 480
            }
        },
        {
            "name": "Test2",
            "type": "audio",
            "payload": {
                "title": "title1",
                "url": "url2",
                "shouldAutoplay": true,
            }
        },
        {
            "name": "Test3",
            "type": "audio",
            "payload": {
                "title": "title2",
                "url": "url3",
                "shouldAutoplay": true,
            }
        }
    ]
}
""".data(using: .utf8)!
struct ImageAttachment: Codable {
    let url: URL
    let width: Int
    let height: Int
}
struct AudioAttachment: Codable {
    let title: String
    let url: URL
    let shouldAutoplay: Bool
}
struct Test: Codable {
    let name: String
}
enum Attachment {
    case image(String, ImageAttachment)
    case audio(String, AudioAttachment)
    case unsupported
}
extension Attachment: Codable {
    private enum CodingKeys: String, CodingKey {
        case type
        case name
        case payload
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        let name = try container.decode(String.self, forKey: .name)
        
        let type = try container.decode(String.self, forKey: .type)
        switch type {
        case "image":
            let payload = try container.decode(ImageAttachment.self, forKey: .payload)
            self = .image(name, payload)
        case "audio":
            let payload = try container.decode(AudioAttachment.self, forKey: .payload)
            self = .audio(name, payload)
        default:
            self = .unsupported
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        
        switch self {
        case .image(let name, let payload):
            try container.encode("image", forKey: .type)
            try container.encode(payload, forKey: .payload)
            try container.encode(name, forKey: .name)
        case .audio(let name, let payload):
            try container.encode("audio", forKey: .type)
            try container.encode(payload, forKey: .payload)
            try container.encode(name, forKey: .name)
        case .unsupported:
            let context = EncodingError.Context(codingPath: [], debugDescription: "Invalid attachment.")
            throw EncodingError.invalidValue(self, context)
        }
    }
}
struct Message: Codable {
    let from: String
    let text: String
    let attachments: [Attachment]
}
let decoder = JSONDecoder()
let message = try decoder.decode(Message.self, from: json)
for attachment in message.attachments {
    switch attachment {
    case .image(let name, let payload):
        print("image", name)
        print("image", payload)
    case .audio(let name, let payload):
        print("audio",name)
        print("audio", payload)
    case .unsupported:
        print("unsupported")
    }
}


How to decode and get the value in a json
 
 
Q