gpt4 book ai didi

ios - Swift:解码 JSON 响应并将嵌套的 JSON 存储为字符串或 JSON

转载 作者:行者123 更新时间:2023-12-04 16:24:25 24 4
gpt4 key购买 nike

给定来自网络请求的以下 JSON;如果你想把它解码成一个 Swift 对象,它与 Codable 一致,但你想保留嵌套的 JSON,它是键 configuration_payload 的值,你怎么做是吗?

{
"registration": {
"id": "0000-0000-0000-0000-000",
"device_type": "device",
"state": "provisioning",
"thing_uuid": 999999999,
"discovery_timeout": 10,
"installation_timeout": 90,
"configuration_payload":
{
"title": "Some Title",
"url": "https://www.someurl.com/",
"category": "test",
"views": 9999
}
}
}

使用以下 Swift struct,我希望能够将 configuration_payload 作为 String 获取。

public struct Registration: Codable {
public enum State: String, Codable {
case provisioning, provisioned
}

public let id, deviceType: String
public let state: State
public let error: String?
public let thingUUID: Int?
public let discoveryTimeout, installationTimeout: Int
public let configurationPayload: String?
}

据我所知,Swift 中的 JSONDecoderconfiguration_payload 的值视为嵌套 JSON,并希望将其解码为自己的对象。更令人困惑的是,configuration_payload 并不总是会返回相同的 JSON 结构,它会有所不同,所以我无法创建一个我可以期待的 Swift struct 而只是 JSON需要时再次对其进行编码。我需要能够将值存储为字符串,以说明 configuration_payload 键下 JSON 的变化。

最佳答案

正如其他人已经说过的,你不能只保留一部分而不解码。然而,解码未知数据是微不足道的:

enum RawJsonValue {
case boolean(Bool)
case number(Double)
case string(String)
case array([RawJsonValue?])
case object([String: RawJsonValue])
}

extension RawJsonValue: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()

if let boolValue = try? container.decode(Bool.self) {
self = .boolean(boolValue)
} else if let numberValue = try? container.decode(Double.self) {
self = .number(numberValue)
} else if let stringValue = try? container.decode(String.self) {
self = .string(stringValue)
} else if let arrayValue = try? container.decode([RawJsonValue?].self) {
self = .array(arrayValue)
} else {
let objectValue = try container.decode([String: RawJsonValue].self)
self = .object(objectValue)
}
}

func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()

switch self {
case .boolean(let boolValue):
try container.encode(boolValue)
case .number(let numberValue):
try container.encode(numberValue)
case .string(let stringValue):
try container.encode(stringValue)
case .array(let arrayValue):
try container.encode(arrayValue)
case .object(let objectValue):
try container.encode(objectValue)
}
}
}

现在我们可以根据需要安全地解码并转换为 JSON 字符串:

struct Registration: Codable {
public enum State: String, Codable {
case provisioning, provisioned
}

let id, deviceType: String
let state: State
let error: String?
let thingUUID: Int?
let discoveryTimeout, installationTimeout: Int
let configurationPayload: RawJsonValue?
}

let jsonData = """
{
"id": "0000-0000-0000-0000-000",
"device_type": "device",
"state": "provisioning",
"thing_uuid": 999999999,
"discovery_timeout": 10,
"installation_timeout": 90,
"configuration_payload":
{
"title": "Some Title",
"url": "https://www.someurl.com/",
"category": "test",
"views": 9999
}
}
""".data(using: .utf8)!

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let registration = try! decoder.decode(Registration.self, from: jsonData)

let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase

let payloadString = String(data: try! encoder.encode(registration.configurationPayload), encoding: .utf8)!
print(payloadString) // {"title":"Some Title","views":9999,"url":"https:\/\/www.someurl.com\/","category":"test"}

我能看到的唯一问题是解码十进制数时可能会丢失精度,这是 Foundation JSON 解码器的一个已知问题。此外,还可以删除一些 null 值。这可以通过迭代键并具有特殊的 null 类型手动解码 object 来解决。

关于ios - Swift:解码 JSON 响应并将嵌套的 JSON 存储为字符串或 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68254792/

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