2017-09-19 6 views
4

처음 스위프트 4에서 Codable 프로토콜을 사용하고 있는데 의 사용을 Decodable에서 이해할 수 없습니다.JSON 구문 분석 용 Decodable을 사용할 때 선택 사항과 decodeIfPresent의 차이점은 무엇입니까?

/// Decodes a value of the given type for the given key, if present. 
/// 
/// This method returns `nil` if the container does not have a value associated with `key`, or if the value is null. The difference between these states can be distinguished with a `contains(_:)` call. 
/// 
/// - parameter type: The type of value to decode. 
/// - parameter key: The key that the decoded value is associated with. 
/// - returns: A decoded value of the requested type, or `nil` if the `Decoder` does not have an entry associated with the given key, or if the value is a null value. 
/// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type. 
public func decodeIfPresent(_ type: String.Type, forKey key: KeyedDecodingContainer.Key) throws -> String? 

값이 연관된 키와 함께 표시되지 않으면 nil을 반환하는 것이 좋습니다. 이것이 유일한 이유 일 경우 선택적 속성과 값이 다른 점은 선택적 변수로 값이 응답에없는 경우 nil으로 설정됩니다.

+1

이 메소드는'String? '을 반환한다는 것을 알고 있습니까? 이것은 선택 사항입니까? 그래서 기본적으로 당신이 옳습니다. 거기에 optionals의 사용 _is_입니다. – Sweeper

답변

12

코드의 두 라인 사이에 미묘하지만 중요한 차이가있다 :

// Exhibit 1 
foo = try container.decode(Int?.self, forKey: .foo) 
// Exhibit 2 
foo = try container.decodeIfPresent(Int.self, forKey: .foo) 

전시는 1 구문 분석됩니다

{ 
    "foo": null, 
    "bar": "something" 
} 

하지만 을하지 :

{ 
    "bar": "something" 
} 

동안 전시회 2는 행복하게 둘 다 구문 분석합니다. 따라서 일반적인 사용 사례 인 JSON 파서의 경우 모델의 모든 선택 항목에 대해 decodeIfPresent을 입력해야합니다.

0

예, @ 스위퍼의 의견은 이해가됩니다. 어떻게, 나는 그것을 관찰 할 수 없다.

나는 내 이해에 따라 설명하려고합니다.

public class User : Decodable{ 

    public var firstName:String 
    public var lastName:String 
    public var middleName:String? 
    public var address:String 
    public var contactNumber:String 


    public enum UserResponseKeys: String, CodingKey{ 
     case firstName = "first_name" 
     case lastName = "last_name" 
     case middleName = "middle_name" 
     case address = "address" 
     case contactNumber = "contact_number" 
    } 

    public required init(from decoder: Decoder) throws { 

     let container = try decoder.container(keyedBy: UserResponseKeys.self) 

     self.firstName = try container.decode(String.self, forKey: .firstName) 
     self.lastName = try container.decode(String.self, forKey: .lastName) 
     self.middleName = try container.decodeIfPresent(String.self, forKey: .middleName) 
     self.address = try container.decode(String.self, forKey: .address) 
     self.contactNumber = try container.decode(String.self, forKey: .contactNumber) 
    } 

} 

위는 middleName이 선택적 매개 변수 인 내 User 클래스, 그래서 내가 선택 (middleName:String?)로 표시, 그래서 nil을 수용 할 수있는 나는, 옵션 전용 변수에 대한 decodeIfPresent를 사용할 수 있습니다.

필수 입력란 인 다른 변수에 대해서는 필수 입력란을 사용하지 않아도됩니다. 그 방법은 선택 사항을 반환하지 않기 때문에 우리는 단지 decode만을 사용했습니다. decode 기능 이상

public func decode(_ type: String.Type, forKey key: KeyedDecodingContainer.Key) throws -> String 

StringdecodeIfPresent 동안 반환 String?를 반환, 그래서 우리는 그것을 저장하는 옵션 변수를 사용할 수 있습니다.