2017-10-26 9 views
0

서버의 JSON 응답을 포함하는 Data 객체가 있습니다. Data 초기에 그때 Data 다시이 객체를 ENDCODE하고 싶습니다 테스트 목적으로코드 분할 변환 전후의 JSON 데이터 비교

let object = try JSONDecoder().decode(Object.self, from: response.data) 

비교 :

그것은 일부 Codable 객체에 이런 식으로 변환됩니다.

let data = try JSONEncoder().encode(object) 

1 가정 : Data 객체가 디코드 + 인코딩 후 동일한 경우, 그것은 모든 필드를 올바르게 내 Codablestruct에 나열되어 있음을 의미, 모든 필드는 변환 후 나는 '... 등 유효한 유형과이 두 Data 개체가 있습니다 : 154362 바이트 154435 바이트. 그것은 그들이 다르다는 것을 의미합니다. 그러나 내가 jsondiff.com을 사용하여 그들을 비교할 때 그들은 100 % 동일하게 보입니다.

두 번째 가정 : 데이터 개체를 String으로 변환하려고 시도했지만 JSON 구조가 다른 방식으로 정렬되었습니다. 따라서이 방법은 작동하지 않습니다.

Double/Float 값에는 몇 가지 문제가 있습니다. 이들은 디코딩 중에 다음과 같이 해석됩니다. 41.01 결과는 41.009999999입니다.

그래서 질문입니다 : 두 개의 JSON 객체가 디코딩 + 인코딩 전후에 동일하다는 것을 검증하는 방법이 있습니까? 현재 솔루션

: 나는 JSONSerialization을 제공하기로 결정이 좋은 쓰기 옵션이있다 시도 때문에 아이폰 OS 11 이후 : 나는에 Data

@available(iOS 11.0, *) 
public static var sortedKeys: JSONSerialization.WritingOptions { get } 

이 방법을 변환 제대로 분류 JSON :

@available(iOS 11, *) 
private extension Data { 

    static func equal(json1: Data, json2: Data) -> Bool { 
     return json1.serialized == json2.serialized 
    } 

    var serialized: Data? { 
     guard let json = try? JSONSerialization.jsonObject(with: self) else { 
      return nil 
     } 
     guard let data = try? JSONSerialization.data(withJSONObject: json, options: [.sortedKeys, .prettyPrinted]) else { 
      return nil 
     } 
     return data 
    } 
} 

두 개의 json Data 개체를 비교하는 신뢰할 수있는 방법입니까?

+0

'JSONEncoder/Decoder'는 매우 제한적입니다. 모순이 있으면 오류가 발생합니다. 작업이 성공하면 데이터가 올바르게 처리되었는지 확인할 수 있습니다. 입력/출력 차이는 부동 소수점 값이 관련된 경우에만 발생합니다. 부동 소수점 값의 정밀도를 제어 할 필요가 있다면'NumberFormatter'을 사용하십시오 – vadian

+0

구조체에 필드가 없지만 초기 json에 존재한다면 오류는 발생하지 않습니다 – iWheelBuy

답변

1

작은 iOS11Data 확장자를 생성하여 JSON 객체를 비교하고 두 개의 JSON 객체가 불일치하기 시작하는 첫 번째 행을 찾는 데 도움이됩니다.

@available(iOS 11, *) 
public extension Data { 

    public func jsonSerialized() -> Data? { 
     guard let json = try? JSONSerialization.jsonObject(with: self) else { 
      return nil 
     } 
     let object: Any = { 
      if let array = json as? Array<Any> { 
       return array.strippingNulls() 
      } else if let dictionary = json as? Dictionary<String, Any> { 
       return dictionary.strippingNulls() 
      } else { 
       return json 
      } 
     }() 
     guard let data = try? JSONSerialization.data(withJSONObject: object, options: [.sortedKeys, .prettyPrinted]) else { 
      return nil 
     } 
     return data 
    } 

    public static func jsonMismatch(lhs: Data, rhs: Data, alreadySerialized: Bool = false) -> Int? { 
     switch alreadySerialized { 
     case true: 
      return _jsonMismatch(lhs: lhs, rhs: rhs) 
     case false: 
      guard let lhs = lhs.jsonSerialized(), let rhs = rhs.jsonSerialized() else { 
       return nil 
      } 
      return _jsonMismatch(lhs: lhs, rhs: rhs) 
     } 
    } 

    private static func _jsonMismatch(lhs: Data, rhs: Data) -> Int? { 
     guard let string1 = String(data: lhs, encoding: .utf8), let string2 = String(data: rhs, encoding: .utf8) else { 
      return nil 
     } 
     let components1 = string1.components(separatedBy: "\n") 
     let components2 = string2.components(separatedBy: "\n") 
     let count = components1.count < components2.count ? components1.count : components2.count 
     for index in 0 ..< count { 
      if components1[index] != components2[index] { 
       return index 
      } 
     } 
     return nil 
    } 
} 

private extension Array where Element == Any { 

    func strippingNulls() -> Array { 
     var array = self 
     array.stripNulls() 
     return array 
    } 

    mutating func stripNulls() { 
     let count = self.count 
     guard count > 0 else { 
      return 
     } 
     for _index in 0 ..< count { 
      let index = count - 1 - _index 
      if self[index] is NSNull { 
       remove(at: index) 
      } else if let array = self[index] as? [Any] { 
       self[index] = array.strippingNulls() 
      } else if let dictionary = self[index] as? [String: Any] { 
       self[index] = dictionary.strippingNulls() 
      } 
     } 
    } 
} 

private extension Dictionary where Key == String, Value == Any { 

    func strippingNulls() -> Dictionary { 
     var dictionary = self 
     dictionary.stripNulls() 
     return dictionary 
    } 

    mutating func stripNulls() { 
     for (key, value) in self { 
      if value is NSNull { 
       removeValue(forKey: key) 
      } else if let array = value as? [Any] { 
       self[key] = array.strippingNulls() 
      } else if let dictionary = value as? [String: Any] { 
       self[key] = dictionary.strippingNulls() 
      } 
     } 
    } 
}