Swift получить JSON с Codable - PullRequest
       15

Swift получить JSON с Codable

0 голосов
/ 26 июня 2018

Я хочу получить json по модели кодирования, которая наследует базовый класс и соответствует протоколу Codable. Но это не удалось. Вот код:

// 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)
}

Я изменил код, как показано ниже, затем func test1() поддержал правый JSON, но func test2() был ошибкой:

class BaseClass {
    var bx = 0
}

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

Ждем вашей помощи!

Ответы [ 3 ]

0 голосов
/ 26 июня 2018

Encodable и Decodable включают в себя некоторый синтез кода, когда компилятор по существу пишет код для вас. Когда вы переводите BaseClass в Codable, эти методы записываются в класс BaseClass и, следовательно, они не знают о каких-либо дополнительных свойствах, определенных SubClass. Вы должны переопределить метод кодирования (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)
    }
}
0 голосов
/ 26 июня 2018

Я изменил ваш код, вы можете проверить его.

 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)
}
0 голосов
/ 26 июня 2018

Вы можете попробовать вот так

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)
}

}

Если вам нужна дополнительная помощь, этот сайт очень полезен для конвертации ваших моделей JSON http://www.json4swift.com

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...