加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

如何在Swift中表示通用的JSON结构?

发布时间:2020-12-14 04:39:44 所属栏目:百科 来源:网络整理
导读:我想在 Swift中表示一个通用的JSON对象: let foo: [String: Any] = [ "foo": 1,"bar": "baz",] 但编译器建议的[String:Any]类型并不能很好地工作.我无法检查该类型的两个实例是否相等,例如,虽然这应该可以使用两个JSON树. 什么也行不通的是使用Codable机制
我想在 Swift中表示一个通用的JSON对象:

let foo: [String: Any] = [
    "foo": 1,"bar": "baz",]

但编译器建议的[String:Any]类型并不能很好地工作.我无法检查该类型的两个实例是否相等,例如,虽然这应该可以使用两个JSON树.

什么也行不通的是使用Codable机制将该值编码为JSON字符串:

let encoded = try JSONEncoder().encode(foo)

哪个因错误而爆炸:

fatal error: Dictionary<String,Any> does not conform to Encodable because Any does not conform to Encodable.

我知道我可以引入一个精确的类型,但我遵循通用的JSON结构.我甚至尝试为泛型JSON引入一种特定类型:

enum JSON {
    case string(String)
    case number(Float)
    case object([String:JSON])
    case array([JSON])
    case bool(Bool)
    case null
}

但是当为这个枚举实现Codable时,我不知道如何实现encode(to :),因为一个带键的容器(用于编码对象)需要一个特定的CodingKey参数,我不知道如何获得它.

是否真的不可能创建一个Equatable通用JSON树并使用Codable对其进行编码?

解决方法

我们将使用通用字符串作为编码键:

extension String: CodingKey {
    public init?(stringValue: String) {
        self = stringValue
    }

    public var stringValue: String {
        return self
    }

    public init?(intValue: Int) {
        return nil
    }

    public var intValue: Int? {
        return nil
    }
}

剩下的只是获取正确类型的容器并将值写入其中.

extension JSON: Encodable {
    public func encode(to encoder: Encoder) throws {
        switch self {
        case .string(let string):
            var container = encoder.singleValueContainer()
            try container.encode(string)
        case .number(let number):
            var container = encoder.singleValueContainer()
            try container.encode(number)
        case .object(let object):
            var container = encoder.container(keyedBy: String.self)

            for (key,value) in object {
                try container.encode(value,forKey: key)
            }
        case .array(let array):
            var container = encoder.unkeyedContainer()

            for value in array {
                try container.encode(value)
            }
        case .bool(let bool):
            var container = encoder.singleValueContainer()
            try container.encode(bool)
        case .null:
            var container = encoder.singleValueContainer()
            try container.encodeNil()
        }
    }
}

鉴于此,我相信你可以自己实现Decodable和Equatable.

请注意,如果您尝试将除数组或对象之外的任何内容编码为顶级元素,则会崩溃.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读