从 JSONDecoder.decode() 的字符串动态获取 class 类型

Get class type dynamically from string for JSONDecoder.decode()

我想解码 json websocket "notification" 的响应,其中通知类型在 json 响应中。

JSON 示例:

{
    "jsonrpc": "2.0",
    "method": "Application.OnVolumeChanged",
    "params": {
        "data": {
            "muted": false,
            "volume": 88.6131134033203125
        },
        "sender": "xbmc"
    }
}

这是我目前拥有的:

func notificationMessage(text: String) {
    do {
        if let jsonData = text.data(using: .utf8),
            let json = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any],
            let method = json["method"] as? String,
            let methodName = method.split(separator: ".").last?.description {

            let decoder = JSONDecoder()
            let object = try decoder.decode(OnVolumeChanged.self, from: jsonData)

            print(object)
        }
    } catch {
        print("Error deserializing JSON: \(error)")
    }
}

现在我想用 methodName 而不是 OnVolumeChanged.self。 但我不想在 methodName 上做一个巨大的 switch case,因为我可以获得数百种不同的方法 我试过 NSClassFromString(methodName) 但这给了我 AnyClass? 这不是具体类型。

有没有办法从字符串中获取 class 类型?

I have faced the same problem and here is my solution. You can add methods to Mapper dictionary any time you want.

//1

let Mapper: [String: Any] = ["OnVolumeChanged"  : OnVolumeChanged.self]

//2

func notificationMessage(text: String) {
                    do {
                        if let jsonData = text.data(using: .utf8),
                            let json = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any],
                            let method = json["method"] as? String,
                            let methodName = method.split(separator: ".").last?.description {

                            let className = Mapper[methodName] as! Codable.Type
                            let object = try className.init(jsonData: jsonData)


                            print(object)
                        }
                    } catch {
                        print("Error deserializing JSON: \(error)")
                    }
                }

//3

extension Decodable {
                    init(jsonData: Data) throws {
                        self = try JSONDecoder().decode(Self.self, from: jsonData)
                    }
                }