简体   繁体   English

Swift使用Codable获取json

[英]Swift get json with Codable

I want get json by encode model, which inherit a base class, and conforms to protocol Codable . 我想通过编码模型获取json,该编码模型继承基类并符合协议Codable But it failed. 但是失败了。 Here is the code: 这是代码:

// this is a func to get json
func getJson<T>(model: T) throws -> String where T: AnyObject, T: Codable {
    let encoder = JSONEncoder()
    let data = try encoder.encode(model)
    if let json = String(data: data, encoding: String.Encoding.utf8) {
        return json
    } else {
        return ""
    }
}


class BaseClass: Codable {
    var bx = 0
}

class SubClass: BaseClass  {
    var x = 1
    var y = 2
}

// test if get json enable
func test1() throws {
    let source = SubClass()
    let json = try getJson(model: source)
    print(json)
}

// how can i get json by this code
func test2() throws {
    let source = SubClass()

    var any: BaseClass?
    any = source
    let json = try getJson(model: any!)
    print(json)
}

I modifed the code like below , then the func test1() backed right json, but func test2() was error : 我修改了如下代码,然后func test1()支持json,但是func test2()错误:

class BaseClass {
    var bx = 0
}

class SubClass: BaseClass, Codable  {
    var x = 1
    var y = 2
}

Looking forward to your help ! 期待您的帮助!

Encodable and Decodable involve some code synthesis where the compiler essentially writes the code for you. Encodable和Decodable涉及一些代码合成,其中编译器实质上是为您编写代码。 When you conform BaseClass to Codable, these methods are written to the BaseClass class and hence they are not aware of any additional properties defined by SubClass. 当使BaseClass符合Codable时,这些方法将写入BaseClass类,因此它们不知道SubClass定义的任何其他属性。 You have to override the encode(to:) method in your subclass: 您必须重写子类中的encode(to :)方法:

class BaseClass: Codable {
    var bx = 0
}

class SubClass: BaseClass  {
    var x = 1
    var y = 2

    private enum CodingKeys: String, CodingKey {
        case x
        case y
    }

    override func encode(to encoder: Encoder) throws {
        try super.encode(to: encoder)
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(self.x, forKey: .x)
        try container.encode(self.y, forKey: .y)
    }
}

You can try like this 你可以这样尝试

let url = URL(string: "http://www.stackoverflow.com")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in  
    let jsonDecoder = JSONDecoder()
    let responseModel = try jsonDecoder.decode(Json4Swift_Base.self, from: data!)

}
task.resume()

struct Json4Swift_Base : Codable {

let gameID : Int?
let start : String?

enum CodingKeys: String, CodingKey {

    case gameID = "gameID"
    case start = "start"

}

init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    gameID = try values.decodeIfPresent(Int.self, forKey: .gameID)
    start = try values.decodeIfPresent(String.self, forKey: .start)
}

}

If you need more help this website is very helpful to convert your json models http://www.json4swift.com 如果您需要更多帮助,则此网站对转换json模型非常有帮助http://www.json4swift.com

I modified your code, you can check it out. 我修改了您的代码,您可以检查出来。

 func getJson<T>(model: T) throws -> String where T: AnyObject, T: Codable {
    let encoder = JSONEncoder()
    let data = try encoder.encode(model)
    if let json = String(data: data, encoding: String.Encoding.utf8) {
        return json
    } else {
        return ""
    }
}


class BaseClass: Codable {
    var x : Int
    var y: Int
    init(x bx: Int, y by: Int) {
        x = bx
        y = by
    }
}

class SubClass: BaseClass {
    override init(x bx: Int, y by: Int) {
        super.init(x: bx, y: by)
    }

    required init(from decoder: Decoder) throws {
        fatalError("init(from:) has not been implemented")
    }
}

// test if get json enable
func test1() throws {
    let source = SubClass(x: 1, y: 6)
    let json = try getJson(model: source)
    print(json)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM