gpt4 book ai didi

Swift4 Decodable - 将一半的键解码为字典

转载 作者:行者123 更新时间:2023-11-28 07:23:19 38 4
gpt4 key购买 nike

我有这样的情况,服务器向我发送了一个模型,我知道一些键的类型和名称,但不知道其他键的类型和名称。但是,用户可以根据自己的意愿编辑其他键值对。

例子:

{ "a": "B",
"b": 42,
"__customKey1": "customVal1",
"__customKey2": [41, 42],
"__customKey3": {"z":"x"}
}

所以我最终想要的是一个模型,其中包含一些声明的属性和一些填充到 Dictionary<String, Any> 中的值。 ,例如

struct MyStruct {
var a: String?
var b: Int?
var dict: Dictionary<String,Any>
}

我试过类似的方法:

  public struct CodingKeysX: CodingKey {
public var intValue: Int?
public var stringValue: String

public init?(intValue: Int) { self.intValue = intValue; self.stringValue = "\(intValue)" }
public init?(stringValue: String) { self.stringValue = stringValue }

static func make(key: String) -> CodingKeysX {
return CodingKeysX(stringValue: key)!
}
}

init(from decoder: Decoder) throws {

let co = try! decoder.container(keyedBy: CodingKeysX.self)

let container = try decoder.container(keyedBy: CodingKeys.self)
self.a = try container.decode(String?.self, forKey: .a)
self.b = try container.decode(Int?.self, forKey: .b)
let allDeclaredKeys = container.allKeys.map({ $0.stringValue })
self.dict = Dictionary<String, Any>()
for key in co.allKeys.filter({ !allDeclaredKeys.contains($0.stringValue) }) {
self.dict[key.stringValue] = try? co.decodeIfPresent(Any.self, forKey: key)
}
}

但是我得到以下编译时错误:

Protocol type 'Any' cannot conform to 'Decodable' because only concrete types can conform to protocols

似乎也使用 JSONDecoder我无法引用原始 Data给我们NSJSONSerialization .所以我想,我可以反过来做,我首先使用旧技术初始化字典,然后使用 JSONDecoder 初始化模型。并用传入数据的东西替换 init,但感觉不对,因为我们会有效地反序列化两次:/

最佳答案

我不同意你应该将其解析为 [String: Any]。 JSON 中只有少数几种合法的值类型。这与 Any 相去甚远。

相反,您的起点 IMO 将是 generic JSON decoder .解码为 JSON 枚举。

let value = try JSONDecoder().decode(JSON.self, from: json)
==> Optional(["__customKey1": "customVal1", "b": 42, "a": "B", "__customKey2": [41, 42], "__customKey3": ["z": "x"]])

value["a"]?.stringValue // Note value is a JSON, not a Dictionary
==> Optional("B")

使用它,为了解决您的特定问题,您可以做这样的事情(非常接近您现有的解码器):

struct MyStruct {
var a: String?
var b: Int?
var dict: [String: JSON] // JSON values, not Any values
}

extension MyStruct: Decodable {

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: JSON.Key.self)

let knownKeys = [JSON.Key("a"), JSON.Key("b")]

// Unload the known keys. There's no need for these to be Optional unless
// they really are optional (and nil is different than ""). The point,
// is you can do any "normal" validation you want here and throw on error.
self.a = try container.decodeIfPresent(String.self, forKey: JSON.Key("a"))
self.b = try container.decodeIfPresent(Int.self, forKey: JSON.Key("b"))

// Unload the rest into your dictionary
self.dict = [:]
for key in container.allKeys where !knownKeys.contains(key) {
self.dict[key.stringValue] = try container.decode(JSON.self, forKey: key)
}
}
}

let ms = try JSONDecoder().decode(MyStruct.self, from: json)
=> MyStruct(a: Optional("B"), b: Optional(42),
dict: ["__customKey1": "customVal1",
"__customKey2": [41, 42],
"__customKey3": {"z": "x"}])

ms.dict["__customKey1"]?.stringValue // Optional("customVal1")

关于Swift4 Decodable - 将一半的键解码为字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57351147/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com