рдлрд┐рд▓рд╣рд╛рд▓, рдЕрдзрд┐рдХрд╛рдВрд╢ рдореЛрдмрд╛рдЗрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд░реНрд╡рд░ рд╣реИрдВред рд╣рд░ рдЬрдЧрд╣ рд▓реЛрдбрд┐рдВрдЧ, рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬреЗрд╢рди, рдЗрд╡реЗрдВрдЯреНрд╕ рднреЗрдЬрдирд╛ рдФрд░ рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рдЗрдВрдЯрд░реИрдХреНрдЯ рдХрд░рдиреЗ рдХрд╛ рдореБрдЦреНрдп рддрд░реАрдХрд╛ json рдлреЙрд░реНрдореЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбреЗрдЯрд╛ рдХрд╛ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рд╣реИред
рдХреБрдВрдЬреА рдбрд┐рдХреЛрдбрд┐рдВрдЧ
рдлрд╛рдЙрдВрдбреЗрд╢рди рдХреЗ рдкрд╛рд╕ рд╕реАрд░рд┐рдпрд▓-рдбреЗ-рдбреЗрдб рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рджреЛ рддрдВрддреНрд░ рд╣реИрдВред рдкреБрд░рд╛рдирд╛ NSJsonSerialization
рдФрд░ рдирдпрд╛ Codable
ред рдлрд╛рдпрджреЗ рдХреА рд╕реВрдЪреА рдореЗрдВ рдЕрдВрддрд┐рдо рдореЗрдВ рдПрдХ рдРрд╕реА рдЕрджреНрднреБрдд рдЪреАрдЬ рд╣реИ рдЬреЛ рд╕рдВрд░рдЪрдирд╛ (рдпрд╛ рд╡рд░реНрдЧ) рдХреЗ рдЖрдзрд╛рд░ рдкрд░ json рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдСрдЯреЛ-рдЬреЗрдирд░реЗрд╢рди рдХреА рдХреА рд╣реИ рдЬреЛ Codable
( Encodable
, Decodable
) рдХреЛ рд▓рд╛рдЧреВ Codable
рдФрд░ рдбрд┐рдХреЛрдбрд┐рдВрдЧ рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ Decodable
ред
рдФрд░ рд╕рдм рдХреБрдЫ рдареАрдХ рд▓рдЧрддрд╛ рд╣реИ, рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЖрдирдВрдж рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡рд┐рдХрддрд╛ рдЗрддрдиреА рд╕рд░рд▓ рдирд╣реАрдВ рд╣реИред
рд╕рд░реНрд╡рд░ рдкрд░ рдЕрдХреНрд╕рд░ рдЖрдк рдлреЙрд░реНрдо рдХреЗ json рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:
{"topLevelObject": { "underlyingObject": 1 }, "Error": { "ErrorCode": 400, "ErrorDescription": "SomeDescription" } }
рдпрд╣ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕рд░реНрд╡рд░реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╕реЗ рд▓рдЧрднрдЧ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЬреАрд╡рди рдХрд╛ рдЙрджрд╛рд╣рд░рдг рд╣реИред
JsonDecoder
рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП, JsonDecoder
snake_case рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдп рдирд┐рд░реНрджрд┐рд╖реНрдЯ JsonDecoder
рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ UpperCamelCase, рдбреИрд╢-рд╕реНрдиреЗрдХ-рдХреЗрд╕ рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╣реЙрдЬ рднреА рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдХреБрдВрдЬрд┐рдпрд╛рдБ рд▓рд┐рдЦрдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВ?
рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, Apple рдиреЗ CodingKeys
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ JSONDecoder.KeyDecodingStrategy
рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд╕рд╛рде рдорд┐рд▓рд╛рди рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдХреБрдВрдЬреА рдореИрдкрд┐рдВрдЧ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХреАред рд╣рдо рдЗрд╕рдХрд╛ рдлрд╛рдпрджрд╛ рдЙрдард╛рдПрдВрдЧреЗред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рд╕рдВрд░рдЪрдирд╛ рдмрдирд╛рдПрдВ рдЬреЛ CodingKey
рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдХреЛрдИ рднреА рдирд╣реАрдВ рд╣реИ:
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 } }
рдлрд┐рд░ рд╣рдорд╛рд░реА рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдорд╛рдорд▓реЗ рдХреЛ рдЕрд▓рдЧ рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдореБрдЦреНрдп рд╣реИрдВ:
snake_case, dash-snake-case, lowCamelCase рдФрд░ UpperCamelCaseред рдЪреЗрдХ, рд░рди, рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рддрдм рд╣рдореЗрдВ рдПрдХ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ: рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд░реВрдк рдореЗрдВ рдХреИрдорд▓рдХреЗрд╕ (рдХрдИ id
, Id
, ID
рдпрд╛рдж рд░рдЦреЗрдВ)ред рдЗрд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЙрдиреНрд╣реЗрдВ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд░реВрдкрд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдФрд░ рдПрдХ рдирд┐рдпрдо рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рд╕рдВрдХреНрд╖рд┐рдкреНрддреАрдХрд░рдг рдХреЛ рдХреИрдорд╕реЗрд▓ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреЗрд╡рд▓ рдкрд╣рд▓рд╛ рдЕрдХреНрд╖рд░ рдХреИрдкрд┐рдЯрд▓ рд░рдЦрдиреЗ рдФрд░ myABBRKey myAbbrKey рдореЗрдВ рдмрджрд▓ рдЬрд╛рдПрдЧрд╛ ред
рдпрд╣ рд╕рдорд╛рдзрд╛рди рдХрдИ рдорд╛рдорд▓реЛрдВ рдХреЗ рд╕рдВрдпреЛрдЬрди рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рдиреЛрдЯ: рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред .custom
рдХреБрдВрдЬреА рдбрд┐рдХреЛрдбрд┐рдВрдЧ рд░рдгрдиреАрддрд┐ред
static func convertToProperLowerCamelCase(keys: [CodingKey]) -> CodingKey { guard let last = keys.last else { assertionFailure() return AnyCodingKey(stringValue: "") } if let fromUpper = convertFromUpperCamelCase(initial: last.stringValue) { return AnyCodingKey(stringValue: fromUpper) } else if let fromSnake = convertFromSnakeCase(initial: last.stringValue) { return AnyCodingKey(stringValue: fromSnake) } else { return AnyCodingKey(last) } }
рдбреЗрдЯ рдбрд┐рдХреЛрдбрд┐рдВрдЧ
рдЕрдЧрд▓реА рдирд┐рдпрдорд┐рдд рд╕рдорд╕реНрдпрд╛ рд╡рд╣ рддрд░реАрдХрд╛ рд╣реИ рдЬрд┐рд╕рд╕реЗ рддрд╛рд░реАрдЦреЗрдВ рдмреАрдд рдЬрд╛рддреА рд╣реИрдВред рд╕рд░реНрд╡рд░ рдкрд░ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕реЗрдЬ рд╣реИрдВ, рдереЛрдбрд╝рд╛ рдХрдо рдХрдорд╛рдВрдб рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рднреА рдПрдХ рд╕рднреНрдп рд░рд╛рд╢рд┐ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рд╣рдореЗрдВ "рд╣рд╛рдВ, рдореИрдВ рдорд╛рдирдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ" рдЬреИрд╕реЗ рддрд╛рд░реАрдЦ рдкреНрд░рд╛рд░реВрдкреЛрдВ рдХреЗ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рдХреЗ рд╕рд╛рде рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝ рд░рд╣рд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХрд┐рд╕реА рдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рддрд╛рд░реАрдЦреЗрдВ, рдХрд┐рд╕реА рдХреЛ рдПрдкреЛрдЪ-рд╕рдордп рдореЗрдВ рдЧреБрдЬрд░рддреА рд╣реИрдВ рдирддреАрдЬрддрди, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдлрд┐рд░ рд╕реЗ рд╕реНрдЯреНрд░рд┐рдВрдЧ-рдирдВрдмрд░- DateDecoder
-рдорд┐рд▓реАрд╕реЗрдХрдВрдб-рд╕реЗрдкрд░реЗрдЯрд░ рдХреЙрдореНрдмрд┐рдиреЗрд╢рди рдХрд╛ рдПрдХ DateDecoder
, рдФрд░ рдЖрдИрдУрдПрд╕ рдореЗрдВ DateDecoder
рд╢рд┐рдХрд╛рдпрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдЦреНрдд рддрд╛рд░реАрдЦ рдкреНрд░рд╛рд░реВрдк рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдпрд╣рд╛рдВ рд╕рдорд╛рдзрд╛рди рд╕рд░рд▓ рд╣реИ, рдмрд╕ рдЦреЛрдЬ рд╕реЗ рд╣рдо рдПрдХ рд╡рд┐рд╢реЗрд╖ рдкреНрд░рд╛рд░реВрдк рдХреЗ рд╕рдВрдХреЗрддреЛрдВ рдХреА рддрд▓рд╛рд╢ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдЖрд╡рд╢реНрдпрдХ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред рдЗрди рд╕реНрд╡рд░реВрдкреЛрдВ рдиреЗ рдореЗрд░реЗ рдорд╛рдорд▓реЛрдВ рдХреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдФрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрд╡рд░ рдХрд┐рдпрд╛ рд╣реИред
рдиреЛрдЯ: рдпрд╣ рдХрд╕реНрдЯрдо рдбреЗрдЯрдлрд╝реЙрд░реНрдорд░ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝рд░ рд╣реИред рдЗрд╕рдХрд╛ рд╕рд┐рд░реНрдл рдлреЙрд░реНрдореЗрдЯ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рд╣реБрдЖ рдлреЙрд░реНрдореЗрдЯрд░ред
static let onlyDate = DateFormatter(format: "yyyy-MM-dd") static let full = DateFormatter(format: "yyyy-MM-dd'T'HH:mm:ss.SSSx") static let noWMS = DateFormatter(format: "yyyy-MM-dd'T'HH:mm:ssZ") static let noWTZ = DateFormatter(format: "yyyy-MM-dd'T'HH:mm:ss.SSS") static let noWMSnoWTZ = DateFormatter(format: "yyyy-MM-dd'T'HH:mm:ss")
рд╣рдо рдЗрд╕реЗ JSONDecoder.DateDecodingStrategy
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдкрдиреЗ рдбрд┐рдХреЛрдбрд░ рд╕реЗ JSONDecoder.DateDecodingStrategy
рдФрд░ рдПрдХ рдбрд┐рдХреЛрдбрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рд▓рдЧрднрдЧ рдХреБрдЫ рднреА рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдПрдХ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╕реБрдкрд╛рдЪреНрдп рд╣реИред
рдкреНрд░рджрд░реНрд╢рди рдкрд░реАрдХреНрд╖рдг
7944 рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рдЬреМрдирд╕ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд▓рд┐рдП рдЯреЗрд╕реНрдЯ рдХрд┐рдП рдЧрдПред
рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдХрд╕реНрдЯрдо Decoder
рд░реВрдкрд╛рдВрддрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рдХреБрдВрдЬреА рдХреЗ рдЕрдирд┐рд╡рд╛рд░реНрдп рд╕рддреНрдпрд╛рдкрди рдХреЗ рдХрд╛рд░рдг json рдореЗрдВ 20% рдзреАрдорд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ Codable
рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдХреЗ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкрдВрдЬреАрдХреГрдд рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рд╢реБрд▓реНрдХ рд╣реИред рдЗрд╕ рдбрд┐рдХреЛрдбрд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд╕рд╛рде рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдмреЙрдпрд▓рд░ рдкреНрд▓реЗрдЯ рдХреА рд╕рдВрдЦреНрдпрд╛ рдмрд╣реБрдд рдХрдо рд╣реЛ рдЧрдИ рд╣реИред рдХреНрдпрд╛ рдореБрдЭреЗ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдбреЗрд╡рд▓рдкрд░ рд╕рдордп рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рдкреНрд░рджрд░реНрд╢рди рдЦрд░рд╛рдм рд╣реЛ рд╕рдХрддрд╛ рд╣реИ? рдпрд╣ рдЖрдк рдкрд░ рдирд┐рд░реНрднрд░ рд╣реИред
рдЧрд┐рдЯрд╣рдм рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдкреВрд░реНрдг рдирдореВрдирд╛ рдХреЛрдб
рдЕрдВрдЧреНрд░реЗрдЬреА рд▓реЗрдЦ