2017-12-04 13 views
1

나는이 같은 JSON 문자열을 역 직렬화 할 수 있습니다디코딩 알 수없는 Encodable 열거 값

을 :

"값"는 열거하고 전체 개체 수 있어야 스위프트 사에서
{ "name" : "John Smith", "value" : "someValue" } 

이 구조체는 같은입니다

struct MyType { 
    name: String? 
    value: Value? 
} 

미래의 새로운 시점에서 백엔드에 새로운 enum 값이 추가 될 수 있으므로 일부 대체 기능을 갖춘 것이 현명 할 것이라고 생각했습니다.

은 내가

enum Value { 
    case someValue 
    case someOtherValue 
    case unknown(value: String) 
} 

같은 열거 형을 만들 수 있다고 생각하지만 난 그냥 열거를 역 직렬화하는 방법 주위에 내 머리를 정리하고 작동 할 수 없습니다. 이전에는 단순히 String enum을 사용했지만 알 수없는 값을 deserialize하면 오류가 발생합니다.

이 작업을 수행하는 간단한 방법이 있습니까? 아니면 String으로 값을 deserialize하고 switch 문을 사용하여 구조체에 사용자 정의 getter를 만들어야합니다. 내보기 모델)?

+1

당신은 쉽게이 초기화 '를 정의 쓸 수 init(from decoder: Decoder)encode(to encoder: Encoder)를 구현하고 명시 적으로 모든 경우를 처리 할 수 ​​있습니다 (코더 :)'중 유형. 그러나 새로운 열거 형 값이 클라이언트 팀 (들)에게 알리지 않고 자신의 백엔드에 추가되면, 기술적으로 해결할 문제는 아닙니다 ... –

+0

알리지 않고 하위 호환성. 업데이트가 게으른 사용자가있을 수 있지만 새로운 enum 값으로 항목을 표시하고 싶습니다. 뭔가 적절한 색상을 선택하거나 특정 아이콘을 표시하는 것과 같은 여러 가지 항목에 대한 열거 형을 사용합니다. 기본값은 최소한 기본 색상과 아이콘을 표시 할 수 있습니다. 단순히 아무것도 표시하지 않는 것이 좋습니다. 내 주요 문제는 하나의 잘못된 열거 형 때문에 아무 항목도 나타나지 않도록 구조체의 전체 배열을 비 직렬화하는 것입니다. – xxtesaxx

+0

어떻게 코드를 작성하려고하는지 추가하십시오. – PGDev

답변

1

당신은 즉

struct MyType: Codable 
{ 
    var name: String? 
    var value: Value? 

    enum CodingKeys: String, CodingKey 
    { 
     case name 
     case value 
    } 

    init(from decoder: Decoder) throws 
    { 
     let values = try decoder.container(keyedBy: CodingKeys.self) 
     name = try values.decode(String.self, forKey: .name) 
     let strValue = try values.decode(String.self, forKey: .value) 
     //You need to handle every case explicitly 
     switch strValue 
     { 
     case "someValue": 
      value = Value.someValue 
     case "someOtherValue": 
      value = Value.someOtherValue 
     default: 
      value = Value.unknown(value: strValue) 
     } 
    } 

    func encode(to encoder: Encoder) throws 
    { 
     var container = encoder.container(keyedBy: CodingKeys.self) 
     try container.encode(name, forKey: .name) 
     if let val = value 
     { 
      //You need to handle every case explicitly 
      switch val 
      { 
      case .someValue, .someOtherValue: 
       try container.encode(String(describing: val), forKey: .value) 
      case .unknown(let strValue): 
       try container.encode(strValue, forKey: .value) 
      } 
     } 
    } 
} 

enum Value 
{ 
    case someValue 
    case someOtherValue 
    case unknown(value: String) 
} 
+0

아, 그래서 열거 형에 사용자 지정 직렬화 코드를 넣으려고하는 대신 구조체에서 사용합니다. 좋은 생각이야. 열거 형에 작은 String -> Value 함수를 작성하여 struct 내부의 값으로 호출 할 수 있습니다. 고마워, 그게 나를 도울 수 – xxtesaxx

+0

그래 .. 도움이된다면 대답을 받아라. – PGDev