程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了如何在Swift 4的Decodable协议中使用自定义键?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决如何在Swift 4的Decodable协议中使用自定义键??

开发过程中遇到如何在Swift 4的Decodable协议中使用自定义键?的问题如何解决?下面主要结合日常开发的经验,给出你关于如何在Swift 4的Decodable协议中使用自定义键?的解决方法建议,希望对你解决如何在Swift 4的Decodable协议中使用自定义键?有所启发或帮助;

手动自定义编码键

在您的示例中,Codable由于所有属性也都符合,因此您将获得自动生成的符合Codable。这种一致性会自动创建一个仅与属性名称相对应的密钥类型,然后将其用于对单个密钥容器进行编码/解码。

但是,这种自动生成的一致性的一个 真正 巧妙的功能是,如果您enum在称为“ CodingKeys” 的类型中定义一个嵌套(或使用typealias具有此名称的a)来符合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现在将使用key 对属性进行编码/解码"zip_code"

有关自动生Encodable/Decodable一致性的确切规则,请参见演进提案(重点是我的):

编码示例:

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

属性名称的自动snake_caseJsON键camelCase

在雨燕4.1,如果您重命名zip属性zipCode,你可以利用关键的编码/解码上的策略JsONEncoder,并JsONDecoder以自动转换之间的编码键camelCasesnake_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密钥映射

在雨燕4.1,您可以利用自定义按键编码/解码上的策略JsONEncoderJsONDecoder,使您可以提供一个自定义函数映射的编码键。

您提供的函数采用[CodingKey],代表编码/解码中当前点的编码路径(在大多数情况下,您只需要虑最后一个元素;即当前键)。该函数返回一个CodingKey它将替换此数组中的最后一个键。

例如,属性名称的UpperCamelCaseJsON键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关键策略进行编码:

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关键策略进行解码:

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

解决方法

Swift
4通过该Decodable协议引入了对本机JSON编码和解码的支持。如何为此使用自定义键?

例如,说我有一个结构

struct Address:Codable {
    var street@R_772_7101@g
    var zip@R_772_7101@g
    var city@R_772_7101@g
    var state@R_772_7101@g
}

我可以将其编码为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","zip_code":"94608","city":"Emeryville" 
}

怎么会告诉解码器上Addresszip_code映射到zip?我相信您使用的是新CodingKey协议,但是我不知道该如何使用。

大佬总结

以上是大佬教程为你收集整理的如何在Swift 4的Decodable协议中使用自定义键?全部内容,希望文章能够帮你解决如何在Swift 4的Decodable协议中使用自定义键?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。