Подтвердить что ты не робот

Как использовать пользовательские ключи с протоколом 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, но я не могу понять, как это использовать.

4b9b3361

Ответ 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 для определенных типов:

  1. Типы, соответствующие Encodable чьи свойства имеют все Encodable получают автоматически сгенерированные свойства CodingKey перечисления String -backed CodingKey с именами дел. Аналогично для Decodable типов, все свойства которых могут быть Decodable

  2. Типы, попадающие в (1) - и типы, которые вручную предоставляют enum CodingKey (называемое CodingKeys, напрямую или через typealias), чьи случаи отображают свойства 1-в-1 на свойства Encodable/Decodable по имени - получают автоматический синтез init(from:) и encode(to:) если необходимо, используя эти свойства и ключи

  3. Типы, которые не попадают ни в (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