Как использовать пользовательские ключи с протоколом Swift 4 Decodable?
Swift 4 представил поддержку собственного кодирования и декодирования JSON через протокол Decodable
. Как использовать для этого специальные клавиши?
Например, скажем, у меня есть структура
struct Address:Codable {
var street:String
var zip:String
var city:String
var state:String
}
Я могу закодировать это на JSON.
let address = Address(street: "Apple Bay Street", zip: "94608", city: "Emeryville", state: "California")
if let encoded = try? encoder.encode(address) {
if let json = String(data: encoded, encoding: .utf8) {
// Print JSON String
print(json)
// JSON string is
{ "state":"California",
"street":"Apple Bay Street",
"zip":"94608",
"city":"Emeryville"
}
}
}
Я могу закодировать это обратно к объекту.
let newAddress: Address = try decoder.decode(Address.self, from: encoded)
Но если у меня был объект json, который был
{
"state":"California",
"street":"Apple Bay Street",
"zip_code":"94608",
"city":"Emeryville"
}
Как я могу сказать декодеру Address
, что zip_code
отображается на zip
? Я считаю, что вы используете новый протокол CodingKey
, но я не могу понять, как это использовать.
Ответы
Ответ 1
Ручная настройка ключей кодирования
В вашем примере вы получаете автоматически сгенерированное соответствие Codable
поскольку все ваши свойства также соответствуют Codable
. Это соответствие автоматически создает тип ключа, который просто соответствует именам свойств - который затем используется для кодирования/декодирования из одного контейнера с ключами.
Однако одна действительно полезная особенность этого автоматически сгенерированного соответствия состоит в том, что если вы определяете вложенный enum
в вашем типе с именем " CodingKeys
" (или используете typealias
с этим именем), который соответствует протоколу CodingKey
- Swift автоматически использует это в качестве ключа тип. Таким образом, это позволяет вам легко настраивать ключи, которыми закодированы/декодированы ваши свойства.
Так что это означает, что вы можете просто сказать:
struct Address : Codable {
var street: String
var zip: String
var city: String
var state: String
private enum CodingKeys : String, CodingKey {
case street, zip = "zip_code", city, state
}
}
Имена регистров перечисления должны совпадать с именами свойств, а необработанные значения этих дел должны совпадать с ключами, из которых вы кодируете/декодируете (если не указано иное, необработанные значения перечисления String
будут такими же, как и регистр). имена). Следовательно, свойство zip
теперь будет кодироваться/декодироваться с использованием ключа "zip_code"
.
Точные правила для автоматически сгенерированного соответствия Encodable
/ Decodable
подробно описаны в предложении об эволюции (выделено мной):
В дополнение к автоматическому CodingKey
требований CodingKey
для enums
могут автоматически синтезироваться требования Encodable
& Decodable
для определенных типов:
-
Типы, соответствующие Encodable
чьи свойства имеют все Encodable
получают автоматически сгенерированные свойства CodingKey
перечисления String
-backed CodingKey
с именами дел. Аналогично для Decodable
типов, все свойства которых могут быть Decodable
-
Типы, попадающие в (1) - и типы, которые вручную предоставляют enum
CodingKey
(называемое CodingKeys
, напрямую или через typealias
), чьи случаи отображают свойства 1-в-1 на свойства Encodable
/Decodable
по имени - получают автоматический синтез init(from:)
и encode(to:)
если необходимо, используя эти свойства и ключи
-
Типы, которые не попадают ни в (1), ни (2), должны будут предоставить пользовательский тип ключа, если необходимо, и предоставить свои собственные init(from:)
и encode(to:)
, в зависимости от ситуации.
Пример кодирования:
import Foundation
let address = Address(street: "Apple Bay Street", zip: "94608",
city: "Emeryville", state: "California")
do {
let encoded = try JSONEncoder().encode(address)
print(String(decoding: encoded, as: UTF8.self))
} catch {
print(error)
}
//{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
Пример декодирования:
// using the """ multi-line string literal here, as introduced in SE-0168,
// to avoid escaping the quotation marks
let jsonString = """
{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
"""
do {
let decoded = try JSONDecoder().decode(Address.self, from: Data(jsonString.utf8))
print(decoded)
} catch {
print(error)
}
// Address(street: "Apple Bay Street", zip: "94608",
// city: "Emeryville", state: "California")
Автоматические JSON-ключи snake_case
для camelCase
свойств camelCase
В Swift 4.1, если вы переименуете свое свойство zip
в zipCode
, вы можете воспользоваться стратегиями кодирования/декодирования JSONEncoder
и JSONDecoder
для автоматического преобразования ключей кодирования между camelCase
и snake_case
.
Пример кодирования:
import Foundation
struct Address : Codable {
var street: String
var zipCode: String
var city: String
var state: String
}
let address = Address(street: "Apple Bay Street", zipCode: "94608",
city: "Emeryville", state: "California")
do {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let encoded = try encoder.encode(address)
print(String(decoding: encoded, as: UTF8.self))
} catch {
print(error)
}
//{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
Пример декодирования:
let jsonString = """
{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
"""
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let decoded = try decoder.decode(Address.self, from: Data(jsonString.utf8))
print(decoded)
} catch {
print(error)
}
// Address(street: "Apple Bay Street", zipCode: "94608",
// city: "Emeryville", state: "California")
Однако следует отметить одну важную вещь, касающуюся этой стратегии: она не сможет выполнять обход некоторых имен свойств с помощью аббревиатур или инициализмов, которые, согласно руководящим принципам разработки Swift API, должны быть равномерно прописными или строчными (в зависимости от положения).
Например, свойство с именем someURL
будет закодировано с помощью ключа some_url
, но при декодировании оно будет преобразовано в someUrl
.
Чтобы исправить это, вам нужно будет вручную указать ключ кодирования для этого свойства в виде строки, которую ожидает декодер, например, someUrl
в этом случае (которая все еще будет преобразована в some_url
кодером):
struct S : Codable {
private enum CodingKeys : String, CodingKey {
case someURL = "someUrl", someOtherProperty
}
var someURL: String
var someOtherProperty: String
}
(Это не дает точного ответа на ваш конкретный вопрос, но, учитывая каноническую природу этих вопросов и ответов, я считаю, что это стоит включить)
Пользовательское автоматическое сопоставление ключей JSON
В Swift 4.1 вы можете воспользоваться преимуществами пользовательских стратегий кодирования/декодирования JSONEncoder
и JSONDecoder
, что позволяет вам предоставлять пользовательские функции для сопоставления ключей кодирования.
Предоставляемая вами функция принимает [CodingKey]
, который представляет путь кодирования для текущей точки кодирования/декодирования (в большинстве случаев вам нужно будет учитывать только последний элемент, то есть текущий ключ). Функция возвращает CodingKey
, который заменит последний ключ в этом массиве.
Например, UpperCamelCase
JSON lowerCamelCase
для lowerCamelCase
свойств lowerCamelCase
:
import Foundation
// wrapper to allow us to substitute our mapped string keys.
struct AnyCodingKey : CodingKey {
var stringValue: String
var intValue: Int?
init(_ base: CodingKey) {
self.init(stringValue: base.stringValue, intValue: base.intValue)
}
init(stringValue: String) {
self.stringValue = stringValue
}
init(intValue: Int) {
self.stringValue = "\(intValue)"
self.intValue = intValue
}
init(stringValue: String, intValue: Int?) {
self.stringValue = stringValue
self.intValue = intValue
}
}
extension JSONEncoder.KeyEncodingStrategy {
static var convertToUpperCamelCase: JSONEncoder.KeyEncodingStrategy {
return .custom { codingKeys in
var key = AnyCodingKey(codingKeys.last!)
// uppercase first letter
if let firstChar = key.stringValue.first {
let i = key.stringValue.startIndex
key.stringValue.replaceSubrange(
i ... i, with: String(firstChar).uppercased()
)
}
return key
}
}
}
extension JSONDecoder.KeyDecodingStrategy {
static var convertFromUpperCamelCase: JSONDecoder.KeyDecodingStrategy {
return .custom { codingKeys in
var key = AnyCodingKey(codingKeys.last!)
// lowercase first letter
if let firstChar = key.stringValue.first {
let i = key.stringValue.startIndex
key.stringValue.replaceSubrange(
i ... i, with: String(firstChar).lowercased()
)
}
return key
}
}
}
Теперь вы можете кодировать с .convertToUpperCamelCase
ключевой стратегии .convertToUpperCamelCase
:
let address = Address(street: "Apple Bay Street", zipCode: "94608",
city: "Emeryville", state: "California")
do {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToUpperCamelCase
let encoded = try encoder.encode(address)
print(String(decoding: encoded, as: UTF8.self))
} catch {
print(error)
}
//{"Street":"Apple Bay Street","City":"Emeryville","State":"California","ZipCode":"94608"}
и декодировать с .convertFromUpperCamelCase
ключевой стратегии .convertFromUpperCamelCase
:
let jsonString = """
{"Street":"Apple Bay Street","City":"Emeryville","State":"California","ZipCode":"94608"}
"""
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromUpperCamelCase
let decoded = try decoder.decode(Address.self, from: Data(jsonString.utf8))
print(decoded)
} catch {
print(error)
}
// Address(street: "Apple Bay Street", zipCode: "94608",
// city: "Emeryville", state: "California")
Ответ 2
В Swift 4.2, в соответствии с вашими потребностями, вы можете использовать одну из 3 следующих стратегий, чтобы имена пользовательских свойств объектов модели соответствовали вашим ключам JSON.
# 1. Использование пользовательских ключей кодирования
Когда вы объявляете структуру, соответствующую протоколам Codable
(Decodable
и Encodable
), со следующей реализацией...
struct Address: Codable {
var street: String
var zip: String
var city: String
var state: String
}
... компилятор автоматически создает вложенное перечисление, соответствующее протоколу CodingKey
.
struct Address: Codable {
var street: String
var zip: String
var city: String
var state: String
// compiler generated
private enum CodingKeys: String, CodingKey {
case street
case zip
case city
case state
}
}
Поэтому, если ключи, используемые в вашем сериализованном формате данных, не совпадают с именами свойств вашего типа данных, вы можете вручную реализовать это перечисление и установить соответствующий rawValue
для требуемых случаев.
В следующем примере показано, как это сделать:
import Foundation
struct Address: Codable {
var street: String
var zip: String
var city: String
var state: String
private enum CodingKeys: String, CodingKey {
case street
case zip = "zip_code"
case city
case state
}
}
Кодирование (замена свойства zip
ключом JSON "zip_code"):
let address = Address(street: "Apple Bay Street", zip: "94608", city: "Emeryville", state: "California")
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(address), let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
}
/*
prints:
{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
*/
Декодирование (замена ключа JSON "zip_code" на свойство zip
):
let jsonString = """
{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
"""
let decoder = JSONDecoder()
if let jsonData = jsonString.data(using: .utf8), let address = try? decoder.decode(Address.self, from: jsonData) {
print(address)
}
/*
prints:
Address(street: "Apple Bay Street", zip: "94608", city: "Emeryville", state: "California")
*/
# 2. Использование кейса-змеи для стратегий кодирования ключей кейса
Если в вашем JSON есть ключи в змеиной оболочке, и вы хотите преобразовать их в свойства в виде верблюдов для своего объекта модели, вы можете установить свои JSONEncoder
keyEncodingStrategy
и JSONDecoder
keyDecodingStrategy
свойства .convertToSnakeCase
.
В следующем примере показано, как это сделать:
import Foundation
struct Address: Codable {
var street: String
var zipCode: String
var cityName: String
var state: String
}
Кодирование (преобразование свойств в верблюжьем корпусе в ключи JSON в виде змеи):
let address = Address(street: "Apple Bay Street", zipCode: "94608", cityName: "Emeryville", state: "California")
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
if let jsonData = try? encoder.encode(address), let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
}
/*
prints:
{"state":"California","street":"Apple Bay Street","zip_code":"94608","city_name":"Emeryville"}
*/
Декодирование (преобразование ключей JSON в корпусе со змеей в свойства верблюда):
let jsonString = """
{"state":"California","street":"Apple Bay Street","zip_code":"94608","city_name":"Emeryville"}
"""
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
if let jsonData = jsonString.data(using: .utf8), let address = try? decoder.decode(Address.self, from: jsonData) {
print(address)
}
/*
prints:
Address(street: "Apple Bay Street", zipCode: "94608", cityName: "Emeryville", state: "California")
*/
# 3. Использование пользовательских стратегий кодирования клавиш
При необходимости JSONEncoder
и JSONDecoder
позволяют вам установить собственную стратегию для сопоставления ключей кодирования, используя JSONEncoder.KeyEncodingStrategy.custom(_:)
и JSONDecoder.KeyDecodingStrategy.custom(_:)
.
В следующем примере показано, как их реализовать:
import Foundation
struct Address: Codable {
var street: String
var zip: String
var city: String
var state: String
}
struct AnyKey: CodingKey {
var stringValue: String
var intValue: Int?
init?(stringValue: String) {
self.stringValue = stringValue
}
init?(intValue: Int) {
self.stringValue = String(intValue)
self.intValue = intValue
}
}
Кодирование (преобразование свойств первой буквы в нижнем регистре в ключи JSON в верхнем регистре):
let address = Address(street: "Apple Bay Street", zip: "94608", city: "Emeryville", state: "California")
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .custom({ (keys) -> CodingKey in
let lastKey = keys.last!
guard lastKey.intValue == nil else { return lastKey }
let stringValue = lastKey.stringValue.prefix(1).uppercased() + lastKey.stringValue.dropFirst()
return AnyKey(stringValue: stringValue)!
})
if let jsonData = try? encoder.encode(address), let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
}
/*
prints:
{"Zip":"94608","Street":"Apple Bay Street","City":"Emeryville","State":"California"}
*/
Декодирование (преобразование ключей JSON в верхнем регистре в первую букву в свойства в нижнем регистре):
let jsonString = """
{"State":"California","Street":"Apple Bay Street","Zip":"94608","City":"Emeryville"}
"""
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .custom({ (keys) -> CodingKey in
let lastKey = keys.last!
guard lastKey.intValue == nil else { return lastKey }
let stringValue = lastKey.stringValue.prefix(1).lowercased() + lastKey.stringValue.dropFirst()
return AnyKey(stringValue: stringValue)!
})
if let jsonData = jsonString.data(using: .utf8), let address = try? decoder.decode(Address.self, from: jsonData) {
print(address)
}
/*
prints:
Address(street: "Apple Bay Street", zip: "94608", city: "Emeryville", state: "California")
*/
Источники:
Ответ 3
Что я сделал, так это создал собственную структуру, такую же, какую вы получаете от JSON в отношении его типов данных.
Именно так:
struct Track {
let id : Int
let contributingArtistNames:String
let name : String
let albumName :String
let copyrightP:String
let copyrightC:String
let playlistCount:Int
let trackPopularity:Int
let playlistFollowerCount:Int
let artistFollowerCount : Int
let label : String
}
После этого вам нужно создать расширение той же struct
расширяющее decodable
и enum
той же структуры с помощью CodingKey
а затем вам нужно инициализировать декодер, используя это перечисление с его ключами и типами данных (ключи будут получены из перечисления, и типы данных будут приходите или говорите по ссылкам из самой структуры)
extension Track: Decodable {
enum TrackCodingKeys: String, CodingKey {
case id = "id"
case contributingArtistNames = "primaryArtistsNames"
case spotifyId = "spotifyId"
case name = "name"
case albumName = "albumName"
case albumImageUrl = "albumImageUrl"
case copyrightP = "copyrightP"
case copyrightC = "copyrightC"
case playlistCount = "playlistCount"
case trackPopularity = "trackPopularity"
case playlistFollowerCount = "playlistFollowerCount"
case artistFollowerCount = "artistFollowers"
case label = "label"
}
init(from decoder: Decoder) throws {
let trackContainer = try decoder.container(keyedBy: TrackCodingKeys.self)
if trackContainer.contains(.id){
id = try trackContainer.decode(Int.self, forKey: .id)
}else{
id = 0
}
if trackContainer.contains(.contributingArtistNames){
contributingArtistNames = try trackContainer.decode(String.self, forKey: .contributingArtistNames)
}else{
contributingArtistNames = ""
}
if trackContainer.contains(.spotifyId){
spotifyId = try trackContainer.decode(String.self, forKey: .spotifyId)
}else{
spotifyId = ""
}
if trackContainer.contains(.name){
name = try trackContainer.decode(String.self, forKey: .name)
}else{
name = ""
}
if trackContainer.contains(.albumName){
albumName = try trackContainer.decode(String.self, forKey: .albumName)
}else{
albumName = ""
}
if trackContainer.contains(.albumImageUrl){
albumImageUrl = try trackContainer.decode(String.self, forKey: .albumImageUrl)
}else{
albumImageUrl = ""
}
if trackContainer.contains(.copyrightP){
copyrightP = try trackContainer.decode(String.self, forKey: .copyrightP)
}else{
copyrightP = ""
}
if trackContainer.contains(.copyrightC){
copyrightC = try trackContainer.decode(String.self, forKey: .copyrightC)
}else{
copyrightC = ""
}
if trackContainer.contains(.playlistCount){
playlistCount = try trackContainer.decode(Int.self, forKey: .playlistCount)
}else{
playlistCount = 0
}
if trackContainer.contains(.trackPopularity){
trackPopularity = try trackContainer.decode(Int.self, forKey: .trackPopularity)
}else{
trackPopularity = 0
}
if trackContainer.contains(.playlistFollowerCount){
playlistFollowerCount = try trackContainer.decode(Int.self, forKey: .playlistFollowerCount)
}else{
playlistFollowerCount = 0
}
if trackContainer.contains(.artistFollowerCount){
artistFollowerCount = try trackContainer.decode(Int.self, forKey: .artistFollowerCount)
}else{
artistFollowerCount = 0
}
if trackContainer.contains(.label){
label = try trackContainer.decode(String.self, forKey: .label)
}else{
label = ""
}
}
}
Здесь необходимо изменить каждый ключ и типы данных в соответствии с вашими потребностями и использовать их с декодером.
Ответ 4
Используя CodingKey, вы можете использовать пользовательские ключи в кодируемом или декодируемом протоколе.
struct person: Codable {
var name: String
var age: Int
var street: String
var state: String
private enum CodingKeys: String, CodingKey {
case name
case age
case street = "Street_name"
case state
} }
Ответ 5
Currently we are using gloss framework for json parsing.We need to migrate gloss to Codable model.
**ClaimActivityListModel:**
import Foundation
import Gloss
public struct ClaimActivityListModel {
// MARK: - Properties
public let claims: [ClaimsActivityModel]
public let moreRecordsPresent: Bool
public init() {
self.claims = []
self.moreRecordsPresent = false
}
}
extension ClaimActivityListModel: Glossy {
public init?(json: Gloss.JSON) {
guard let claim: [ClaimsActivityModel] = "claims" <-- json,
let moreRecordsPresent: Bool = "moreRecordsPresent" <-- json else {
return nil
}
self.claims = claim
self.moreRecordsPresent = moreRecordsPresent
}
public func toJSON() -> Gloss.JSON? { return nil }
}
**ClaimActivityStatus:**
public enum ClaimActivityStatus: String {
case processing = "PROCESSING"
case processed = "PROCESSED"
case paid = "PAID"
case notpaid = "NOT PAID"
}
public struct ClaimActivityItemsModel {
// MARK: - Properties
public let id: String
public let code: String
public let description: String?
public let serviceDate: Date?
public let status: ClaimActivityStatus
public let quantity: Int
public let chargeAmount: Double
public let benefitAmount: Double
public let bonusAmount: Double?
public let pharmacyName: String?
public var showDetails = false
}
extension ClaimActivityItemsModel: Glossy {
public init?(json: Gloss.JSON) {
guard let id: String = "id" <-- json,
let code: String = "code" <-- json,
let status: ClaimActivityStatus = "status" <-- json,
let quantity: Int = "quantity" <-- json,
let chargeAmount: Double = "chargeAmount" <-- json,
let benefitAmount: Double = "benefitAmount" <-- json else {
return nil
}
self.id = id
self.code = code
self.description = "description" <-- json
let serviceDateString: String? = "serviceDate" <-- json
if let servicedatestring = serviceDateString {
self.serviceDate = Date.shortStyle(from: servicedatestring)
} else {
self.serviceDate = nil
}
self.status = status
self.quantity = quantity
self.chargeAmount = chargeAmount
self.benefitAmount = benefitAmount
self.bonusAmount = "bonusAmount" <-- json
self.pharmacyName = "pharmacyName" <-- json
}
public func toJSON() -> Gloss.JSON? { return nil }
}
**ClaimsActivityModel:**
import Foundation
import Gloss
public struct ClaimsActivityModel {
// MARK: - Properties
public let id: String
public let type: ClaimType
public var referenceNumber: String?
public var status: ClaimActivityStatus
public let compensationDamage: Bool
public let submissionDate: Date?
public let bpId: String?
public let payTo: PayTo
public let providerName: String?
public let providerNumber: String?
public let providerAddressLine1: String?
public let providerAddressLine2: String?
public let providerAddressLine3: String?
public let providerSuburb: String?
public let providerPostcode: String?
public let practiceTypeCode: String?
public let practiceTypeDescription: String?
public let claimActivityItems: [ClaimActivityItemsModel]
public let totalChargeAmount: Double
public let totalBonusPaidAmount: Double
public let totalBenefitPaidAmount: Double
public let totalPaidAmount: Double
public let patientName: String?
public var providerDisplayName: String?
public let memberChoiceProvider: Bool
public let reward: ClaimsRewardModel?
public let isAuthorised: Bool
}
extension ClaimsActivityModel: Glossy {
public init?(json: Gloss.JSON) {
let id: String? = "id" <-- json
let status: ClaimActivityStatus? = "status" <-- json
let totalChargeAmount: Double? = "totalChargeAmount" <-- json
let totalBonusPaidAmount: Double? = "totalBonusPaidAmount" <-- json
let totalBenefitPaidAmount: Double? = "totalBenefitPaidAmount" <-- json
let totalPaidAmount: Double? = "totalPaidAmount" <-- json
let reward: ClaimsRewardModel? = "rewards" <-- json
guard (id != nil
&& status != nil
&& totalChargeAmount != nil
&& totalBonusPaidAmount != nil
&& totalBenefitPaidAmount != nil
&& totalPaidAmount != nil)
|| reward != nil else {
return nil
}
self.id = id ?? ""
self.type = "type" <-- json ?? .none
self.referenceNumber = "referenceNumber" <-- json
self.status = status ?? .processing
self.compensationDamage = "compensationDamage" <-- json ?? false
let submissionDateString: String = "submissionDate" <-- json ?? ""
self.submissionDate = Date.shortStyle(from: submissionDateString)
self.bpId = "bpId" <-- json
self.providerName = "providerName" <-- json ?? ""
self.providerNumber = "providerNumber" <-- json
self.providerAddressLine1 = "providerAddressLine1" <-- json
self.providerAddressLine2 = "providerAddressLine2" <-- json
self.providerAddressLine3 = "providerAddressLine3" <-- json
self.providerSuburb = "providerSuburb" <-- json
self.providerPostcode = "providerPostcode" <-- json
self.practiceTypeCode = "practiceTypeCode" <-- json
self.practiceTypeDescription = "practiceTypeDescription" <-- json
self.claimActivityItems = "items" <-- json ?? []
self.totalChargeAmount = totalChargeAmount ?? 0
self.totalBonusPaidAmount = totalBonusPaidAmount ?? 0
self.totalBenefitPaidAmount = totalBenefitPaidAmount ?? 0
self.totalPaidAmount = totalPaidAmount ?? 0
self.payTo = "payTo" <-- json ?? .none
self.patientName = "patientName" <-- json
self.memberChoiceProvider = "memberChoiceProvider" <-- json ?? false
self.reward = reward
self.isAuthorised = "authorized" <-- json ?? true
}
public func toJSON() -> Gloss.JSON? { return nil }
}
// MARK: - ClaimsRewardModel
public struct ClaimsRewardModel {
public let id: String
public let usedAmount: Double
public let availableAmount: Double
}
// MARK: - Glossy
extension ClaimsRewardModel: Glossy {
public init?(json: Gloss.JSON) {
guard let id: String = "rewardId" <-- json,
let usedAmount: Double = "usedAmount" <-- json,
let availableAmount: Double = "availableAmount" <-- json else {
return nil
}
self.id = id
self.usedAmount = usedAmount
self.availableAmount = availableAmount
}
public func toJSON() -> Gloss.JSON? { return nil }
}
Please help me how to migrate this models into Codable
Thanks in advance