使用可编码时,JSON输入表示可编码类型

问题描述:

的多个子类比方说,我有一些JSON,就像这样:使用可编码时,JSON输入表示可编码类型

{ 
    "some-random-key": { 
         "timestamp": 1234123423 
         "type": "text", 
         "content": "Hello!" 
        }, 

    "some-other-key": { 
         "timestamp": 21341412314 
         "type": "image", 
         "path": "/path/to/image.png" 
        } 
} 

这JSON表示两个消息的对象。以下是我想代表他们(SWIFT 4):

class Message: Codable { 
    let timestamp: Int 
    // ...codable protocol methods... 
} 

class TextMessage: Message { // first message should map to this class 

    let content: String 

    // ...other methods, including overridden codable protocol methods... 
} 

class ImageMessage: Message { // second message should map to this class 
    let path: String 

    // ...other methods, including overridden codable protocol methods... 
} 

如何使用“类型”属性在JSON告诉可编码初始化其子类?我的第一反应是用一个枚举作为中介机构,这将允许我去串表示和元类型之间去

enum MessageType: String { 
    case image = "image" 
    case text = "text" 

    func getType() -> Message.Type { 
     switch self { 
     case .text: return TextMessage.self 
     case .image: return ImageMessage.self 
     } 
    } 

    init(type: Message.Type) { 
     switch type { 
     case TextMessage.self: self = .text 
     case ImageMessage.self: self = .image 
     default: break 
     } 
    } 
} 

然而,在init这里会导致编译器错误 -
Expression pattern of type 'TextMessage.Type' cannot match values of type 'Message.Type'
是否有规范/接受的方式来处理这种情况?为什么这里的init没有编译getType函数呢?

的“是”关键字检查是否代表元类型元类型的另一个子类。此代码的工作原理:

init(type: Message.Type) { 
    switch type { 
    case is TextMessage.Type: self = .text 
    case is ImageMessage.Type: self = .text 
    } 
} 
+0

请你能提供一个完整的实例吗? – Stoff81

+0

@ Stoff81'MessageType(rawValue:value).getType()'会给你这个值的类型,'MessageType(type:TextMessage.self).rawValue'将返回类型的编码值。 –

+0

嘿,抱歉,但我正在努力看到整个事情作为一个整体工作。无法让它编译。 – Stoff81

我会去的这种做法:

static func createMessage(with json: [String: Any]) -> Message? { 
     guard let typeString = json["type"] as? String, 
     let type = MessageType(rawValue: typeString) else { return nil } 
     switch type { 
     case .image: return ImageMessage(....