Swift Codable에서 속성을 제외하려면 어떻게 해야 합니까?
스위프트의Encodable
/Decodable
Swift 4와 함께 출시된 프로토콜은 JSON(디시리얼라이제이션)을 매우 쾌적하게 만듭니다.그러나 어떤 속성을 인코딩하고 어떤 속성을 디코딩해야 하는지 세밀하게 제어할 수 있는 방법은 아직 찾지 못했습니다.
부속품에서 부동산을 제외하고CodingKeys
enum은 프로세스에서 속성을 완전히 제외합니다만, 보다 세밀한 제어를 할 수 있는 방법이 있습니까?
부호화/복호화할 키 목록은 다음과 같은 유형에 의해 제어됩니다.CodingKeys
(주의:s
(마지막에)컴파일러는 이를 합성할 수 있지만 항상 덮어쓸 수 있습니다.
속성을 제외한다고 가정해 보겠습니다.nickname
부호화와 복호화 양쪽에서:
struct Person: Codable {
var firstName: String
var lastName: String
var nickname: String?
private enum CodingKeys: String, CodingKey {
case firstName, lastName
}
}
비대칭(즉, 인코딩은 하지만 디코딩은 하지 않거나 그 반대)으로 하고 싶은 경우는, 독자적인 실장을 실시할 필요가 있습니다.encode(with encoder: )
그리고.init(from decoder: )
:
struct Person: Codable {
var firstName: String
var lastName: String
// Since fullName is a computed property, it's excluded by default
var fullName: String {
return firstName + " " + lastName
}
private enum CodingKeys: String, CodingKey {
case firstName, lastName, fullName
}
// We don't want to decode `fullName` from the JSON
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
firstName = try container.decode(String.self, forKey: .firstName)
lastName = try container.decode(String.self, forKey: .lastName)
}
// But we want to store `fullName` in the JSON anyhow
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(firstName, forKey: .firstName)
try container.encode(lastName, forKey: .lastName)
try container.encode(fullName, forKey: .fullName)
}
}
커스텀 속성 래퍼 포함 솔루션
struct Person: Codable {
var firstName: String
var lastName: String
@CodableIgnored
var nickname: String?
}
어디에CodableIgnored
이
@propertyWrapper
public struct CodableIgnored<T>: Codable {
public var wrappedValue: T?
public init(wrappedValue: T?) {
self.wrappedValue = wrappedValue
}
public init(from decoder: Decoder) throws {
self.wrappedValue = nil
}
public func encode(to encoder: Encoder) throws {
// Do nothing
}
}
extension KeyedDecodingContainer {
public func decode<T>(
_ type: CodableIgnored<T>.Type,
forKey key: Self.Key) throws -> CodableIgnored<T>
{
return CodableIgnored(wrappedValue: nil)
}
}
extension KeyedEncodingContainer {
public mutating func encode<T>(
_ value: CodableIgnored<T>,
forKey key: KeyedEncodingContainer<K>.Key) throws
{
// Do nothing
}
}
일부 속성을 인코더에서 제외하는 또 다른 방법으로 별도의 코딩 컨테이너를 사용할 수 있습니다.
struct Person: Codable {
let firstName: String
let lastName: String
let excludedFromEncoder: String
private enum CodingKeys: String, CodingKey {
case firstName
case lastName
}
private enum AdditionalCodingKeys: String, CodingKey {
case excludedFromEncoder
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let anotherContainer = try decoder.container(keyedBy: AdditionalCodingKeys.self)
firstName = try container.decode(String.self, forKey: .firstName)
lastName = try container.decode(String.self, forKey: .lastName)
excludedFromEncoder = try anotherContainer(String.self, forKey: . excludedFromEncoder)
}
// it is not necessary to implement custom encoding
// func encode(to encoder: Encoder) throws
// let person = Person(firstName: "fname", lastName: "lname", excludedFromEncoder: "only for decoding")
// let jsonData = try JSONEncoder().encode(person)
// let jsonString = String(data: jsonData, encoding: .utf8)
// jsonString --> {"firstName": "fname", "lastName": "lname"}
}
디코더에도 같은 어프로치를 사용할 수 있다
구조체의 큰 속성 집합에서 두 개의 속성 디코딩을 제외해야 할 경우 옵션 속성으로 선언하십시오.옵션 래핑 해제 코드는 CodingKey 열거 아래에 많은 키를 쓰는 것보다 작습니다.
확장 기능을 사용하여 계산된 인스턴스 속성 및 계산된 유형 속성을 추가할 것을 권장합니다.코드화 가능한 컴포밍 속성을 다른 로직과 분리하기 때문에 가독성이 향상됩니다.
계산된 속성을 사용할 수 있습니다.
struct Person: Codable {
var firstName: String
var lastName: String
var nickname: String?
var nick: String {
get {
nickname ?? ""
}
}
private enum CodingKeys: String, CodingKey {
case firstName, lastName
}
}
이것은 할 수 있지만 결국 매우 현명하지 못하고 심지어 JSONy도 할 수 없게 된다.네가 어디서 왔는지 알 것 같아#id
s는 HTML에서 널리 사용되고 있지만, 거의 전송되지 않습니다.JSON
좋은 점(TM)이라고 생각합니다.
몇개Codable
구조체에서는 다음 정보를 해석할 수 있습니다.JSON
재귀 해시를 사용하여 재구성하면 파일 상태가 양호합니다.recipe
배열을 포함하고 있을 뿐이다ingredients
차례로 (하나 또는 여러 개)를 포함하는ingredient_info
이렇게 하면 파서를 통해 네트워크를 연결할 수 있습니다.필요한 경우 간단한 트래버설을 통해 백링크를 제공하기만 하면 됩니다.이 작업에는 사용자의 작업 환경을 완전히 수정해야 합니다.JSON
그리고 당신의 데이터 구조를 당신이 생각해 볼 수 있도록 대략적으로만 설명하겠습니다.괜찮으시다면 코멘트로 알려주시면 더 자세히 설명해드릴 수 있습니다만, 상황에 따라서는 어느 쪽도 변경할 수 없는 경우가 있습니다.
프로토콜과 확장 기능을 Associated Object와 함께 사용하여 이미지(또는 코드블에서 제외해야 하는 속성)를 설정하고 가져옵니다.
이것에 의해, 독자적인 인코더와 디코더를 실장할 필요는 없습니다.
다음은 단순화를 위해 관련 코드를 유지하는 코드입니다.
protocol SCAttachmentModelProtocol{
var image:UIImage? {get set}
var anotherProperty:Int {get set}
}
extension SCAttachmentModelProtocol where Self: SCAttachmentUploadRequestModel{
var image:UIImage? {
set{
//Use associated object property to set it
}
get{
//Use associated object property to get it
}
}
}
class SCAttachmentUploadRequestModel : SCAttachmentModelProtocol, Codable{
var anotherProperty:Int
}
Image 속성에 액세스하고 싶을 때마다 Confirming to protocol(SCAttraction Model Protocol) 객체에 사용할 수 있습니다.
언급URL : https://stackoverflow.com/questions/44655562/how-to-exclude-properties-from-swift-codable
'source' 카테고리의 다른 글
angular.defined의 이점은 무엇입니까? (0) | 2023.04.06 |
---|---|
Word press 메뉴 링크에 클래스 추가 (0) | 2023.04.06 |
Oracle 고유 제약 조건 및 고유 인덱스 (0) | 2023.04.06 |
뉴턴소프트 사용법Asp.net Core Web API에서 Json을 기본값으로 설정하시겠습니까? (0) | 2023.04.06 |
IIS 서버 web.config 파일의 위치 (0) | 2023.04.06 |