首页 > 解决方案 > 如何在 Realm 版本 10.15.0 中将数据转换为 Json

问题描述

在领域版本 10.7.1 中,它使用了此代码,但是当迁移到 10.15.0 时,它不再可能,因为 ListBase 类不再存在

extension Object {
    func toWebServiceRequest() -> [String:AnyObject] {
        let properties = self.objectSchema.properties.map { $0.name }
        var dicProps = [String:AnyObject]()
        for (key, value) in self.dictionaryWithValues(forKeys: properties) {
            if let value = value as? ListBase {
                dicProps[key] = value.toArray() as AnyObject
            } else if let value = value as? Object {
                dicProps[key] = value.toWebServiceRequest() as AnyObject
            } else {
                dicProps[key] = value as AnyObject
            }
        }
        return dicProps
    }
}
extension ListBase {
    func toArray() -> [AnyObject] {
        var _toArray = [AnyObject]()
        for i in 0..<self._rlmArray.count {
            let obj = unsafeBitCast(self._rlmArray[i], to: Object.self)
            _toArray.append(obj.toWebServiceRequest() as AnyObject)
        }
        return _toArray
    }
}

标签: jsonswiftobjectrealm

解决方案


mongo 团队希望您使用Codable协议而不是一些自定义编码机制。这确实是正确的方法,否则您必须依赖Realm实现细节。

class Parent: Object, Codable {
    @Persisted var name: String = ""
    @Persisted var children: List<Child>

    convenience init(name: String, children: [Child] = []) {
        self.init()
        self.name = name
        self.children.append(objectsIn: children)
    }
}

如果服务器期望的键与您的对象的属性名称不同,您可以定义自定义 CodingKeys:

class Child: Object, Codable {
    @Persisted var id: Int = 0
    @Persisted var name: String = ""

    enum CodingKeys: String, CodingKey {
        case id = "_id"
        case name = "name"
    }

    convenience init(id: Int, name: String) {
        self.init()
        self.id = id
        self.name = name
    }
}

用法很简单:

func makeParent() -> Parent {
    Parent(name: "Alex", children: [
        Child(id: 1, name: "Jim"),
        Child(id: 2, name: "Tom"),
        Child(id: 3, name: "Sam"),
        Child(id: 4, name: "Joe"),
    ])
}

func encode<Item: Encodable>(_ item: Item) throws -> Data {
    let encoder = JSONEncoder()
    return try encoder.encode(item)
}

func convertDataToString(_ data: Data) throws -> String? {
    return String(data: data, encoding: .utf8)
}

func decode<Item: Decodable>(_ type: Item.Type, from data: Data) throws -> Item {
    let decoder = JSONDecoder()
    return try decoder.decode(type, from: data)
}

func executeProgram() throws {
    let parent = makeParent()
    let encodedJSONData = try encode(parent)

    guard let encodedJSONString = try convertDataToString(encodedJSONData) else {
        throw Error.badJSON
    }

    print("JSON: \(encodedJSONString)")

    let decodedParent = try decode(Parent.self, from: encodedJSONData)

    print("Decoded Parent: \(decodedParent)")
}

在编码路线上,这会导致:

JSON: {"name":"Alex","children":[{"_id":1,"name":"Jim"},{"_id":2,"name":"Tom"},{" _id":3,"name":"Sam"},{"_id":4,"name":"Joe"}]}

在解码路线上,这会导致:

解码父级:父级 { name = Alex; 孩子 = 列表 <0x600000a2b800> ( [0] 孩子 { id = 1; 姓名 = Jim; }, [1] 孩子 { id = 2; 姓名 = 汤姆; }, [2] 孩子 { id = 3; 姓名 = Sam; }, [3] 孩子 { id = 4; 姓名 = 乔; } ); }

您显然可以省略String转换,只使用结果Data


推荐阅读