मैन्युअल रूप से कोडिंग कुंजी को अनुकूलित करना
आपके उदाहरण में, आपको स्वतः-जेनरेट की गई अनुरूपता मिल रही है Codable
क्योंकि आपकी सभी संपत्तियाँ भी अनुरूप हैं Codable
। यह अनुरूपता स्वचालित रूप से एक कुंजी प्रकार बनाती है जो बस संपत्ति के नामों से मेल खाती है - जो तब उपयोग किया जाता है ताकि एक एकल बंद कंटेनर से सांकेतिक शब्दों में बदलना / डिकोड किया जा सके।
हालांकि एक सच में यह स्वत: जनरेट अनुरूपता का साफ सुविधा है कि आप एक नेस्ट को परिभाषित करता है, तो enum
अपने प्रकार "कहा जाता है में CodingKeys
" (या एक का उपयोग typealias
इस नाम के साथ) है कि के अनुरूप CodingKey
प्रोटोकॉल - स्विफ्ट स्वचालित रूप से उपयोग करेगा इस कुंजी प्रकार के रूप में। इसलिए यह आपको उन कुंजियों को आसानी से कस्टमाइज़ करने की अनुमति देता है, जिनके साथ आपकी संपत्तियाँ एन्कोडेड / डिकोड की गई हैं।
तो इसका मतलब क्या है आप बस इतना कह सकते हैं:
struct Address : Codable {
var street: String
var zip: String
var city: String
var state: String
private enum CodingKeys : String, CodingKey {
case street, zip = "zip_code", city, state
}
}
एनुम केस नामों को संपत्ति के नामों से मेल खाना चाहिए, और इन मामलों के कच्चे मूल्यों को उन कुंजियों से मेल खाना चाहिए, जिन्हें आप / से डिकोडिंग कर रहे हैं (जब तक कि अन्यथा निर्दिष्ट नहीं किया जाता है, तो String
एन्यूमरेशन के कच्चे मान केस नामों के समान होंगे। )। इसलिए, zip
अब कुंजी का उपयोग करके संपत्ति को एनकोड / डिकोड किया जाएगा "zip_code"
।
ऑटो-जनरेट Encodable
/ Decodable
अनुरूपता के सटीक नियम विकास प्रस्ताव (जोर मेरा) द्वारा विस्तृत हैं :
के लिए स्वत: CodingKey
आवश्यकता संश्लेषण के
अलावा enums
, Encodable
और Decodable
आवश्यकताओं को स्वचालित रूप से कुछ प्रकारों के लिए भी संश्लेषित किया जा सकता है:
Encodable
जिनके गुण के अनुरूप सभी प्रकार के नाम Encodable
उत्पन्न करने के लिए स्वचालित रूप से उत्पन्न होने वाली String
एनुम CodingKey
मैपिंग गुण हैं। इसी प्रकार के Decodable
प्रकार जिनके गुण सभी हैंDecodable
(1) में आने वाले प्रकारCodingKey
enum
CodingKeys
typealias
Encodable
Decodable
- और प्रकार जो मैन्युअल रूप से एक (नाम , सीधे या एक के माध्यम से ) प्रदान करते हैं, जिनके मामले नाम से 1-से -1 / गुण का नक्शा करते हैं - उन गुणों और कुंजियों का उपयोग करके, init(from:)
और encode(to:)
जैसा कि उपयुक्त हो, के स्वत: संश्लेषण प्राप्त करें
प्रकार जो न तो (1) और न ही (2) में आते हैं, यदि आवश्यक हो तो एक कस्टम कुंजी प्रकार प्रदान करना होगा init(from:)
और अपने स्वयं के और
encode(to:)
उपयुक्त के रूप में प्रदान करना होगा
उदाहरण एन्कोडिंग:
import Foundation
let address = Address(street: "Apple Bay Street", zip: "94608",
city: "Emeryville", state: "California")
do {
let encoded = try JSONEncoder().encode(address)
print(String(decoding: encoded, as: UTF8.self))
} catch {
print(error)
}
//{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
उदाहरण डिकोडिंग:
// using the """ multi-line string literal here, as introduced in SE-0168,
// to avoid escaping the quotation marks
let jsonString = """
{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
"""
do {
let decoded = try JSONDecoder().decode(Address.self, from: Data(jsonString.utf8))
print(decoded)
} catch {
print(error)
}
// Address(street: "Apple Bay Street", zip: "94608",
// city: "Emeryville", state: "California")
संपत्ति के नाम के snake_case
लिए स्वचालित JSON कुंजियाँcamelCase
स्विफ्ट 4.1 में, यदि आप अपनी zip
संपत्ति का नाम बदल देते हैं, तो आप zipCode
कुंजी एन्कोडिंग / डिकोडिंग रणनीतियों का लाभ उठा सकते हैं JSONEncoder
और JSONDecoder
स्वचालित रूप से camelCase
और के बीच कोडिंग कुंजी को बदलने के लिए snake_case
।
उदाहरण एन्कोडिंग:
import Foundation
struct Address : Codable {
var street: String
var zipCode: String
var city: String
var state: String
}
let address = Address(street: "Apple Bay Street", zipCode: "94608",
city: "Emeryville", state: "California")
do {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let encoded = try encoder.encode(address)
print(String(decoding: encoded, as: UTF8.self))
} catch {
print(error)
}
//{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
उदाहरण डिकोडिंग:
let jsonString = """
{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
"""
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let decoded = try decoder.decode(Address.self, from: Data(jsonString.utf8))
print(decoded)
} catch {
print(error)
}
// Address(street: "Apple Bay Street", zipCode: "94608",
// city: "Emeryville", state: "California")
इस रणनीति के बारे में ध्यान देने वाली एक महत्वपूर्ण बात यह है कि यह कुछ संपत्ति के नामों को राउंड-ट्रिप करने में सक्षम नहीं होगा, जो कि स्विफ्ट एपीआई डिजाइन दिशानिर्देशों के अनुसार , समान रूप से ऊपरी या निचले मामले (स्थिति के आधार पर) होना चाहिए )।
उदाहरण के लिए, एक संपत्ति का नाम someURL
कुंजी के साथ एन्कोड किया जाएगा some_url
, लेकिन डिकोडिंग पर, इसे बदल दिया जाएगा someUrl
।
इसे ठीक करने के लिए, आपको मैन्युअल रूप से उस प्रॉपर्टी के लिए कोडिंग कुंजी निर्दिष्ट करनी होगी जो कि डिकोडर को उम्मीद है, जैसे someUrl
इस मामले में (जो अभी भी some_url
एनकोडर द्वारा बदल दिया जाएगा ):
struct S : Codable {
private enum CodingKeys : String, CodingKey {
case someURL = "someUrl", someOtherProperty
}
var someURL: String
var someOtherProperty: String
}
(यह आपके विशिष्ट प्रश्न का कड़ाई से जवाब नहीं देता है, लेकिन इस प्रश्नोत्तर की विहित प्रकृति को देखते हुए, मुझे लगता है कि यह शामिल है)
कस्टम स्वचालित JSON कुंजी मैपिंग
स्विफ्ट 4.1 में, आप कस्टम कुंजी एन्कोडिंग / डिकोडिंग रणनीतियों का लाभ उठा सकते हैं JSONEncoder
और JSONDecoder
, आपको कोडन कुंजी को मैप करने के लिए एक कस्टम फ़ंक्शन प्रदान करने की अनुमति देता है।
आपके द्वारा प्रदान किया जाने वाला फ़ंक्शन एक लेता है [CodingKey]
, जो एन्कोडिंग / डिकोडिंग में वर्तमान बिंदु के लिए कोडिंग पथ का प्रतिनिधित्व करता है (ज्यादातर मामलों में, आपको केवल अंतिम तत्व पर विचार करने की आवश्यकता होगी; वह है, वर्तमान कुंजी)। फ़ंक्शन देता है CodingKey
जो इस सरणी में अंतिम कुंजी को बदल देगा।
उदाहरण के लिए, UpperCamelCase
JSON कुंजियाँlowerCamelCase
संपत्ति के नाम के :
import Foundation
// wrapper to allow us to substitute our mapped string keys.
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
}
}
extension JSONEncoder.KeyEncodingStrategy {
static var convertToUpperCamelCase: JSONEncoder.KeyEncodingStrategy {
return .custom { codingKeys in
var key = AnyCodingKey(codingKeys.last!)
// uppercase first letter
if let firstChar = key.stringValue.first {
let i = key.stringValue.startIndex
key.stringValue.replaceSubrange(
i ... i, with: String(firstChar).uppercased()
)
}
return key
}
}
}
extension JSONDecoder.KeyDecodingStrategy {
static var convertFromUpperCamelCase: JSONDecoder.KeyDecodingStrategy {
return .custom { codingKeys in
var key = AnyCodingKey(codingKeys.last!)
// lowercase first letter
if let firstChar = key.stringValue.first {
let i = key.stringValue.startIndex
key.stringValue.replaceSubrange(
i ... i, with: String(firstChar).lowercased()
)
}
return key
}
}
}
अब आप .convertToUpperCamelCase
मुख्य रणनीति के साथ सांकेतिक शब्दों में बदलना कर सकते हैं :
let address = Address(street: "Apple Bay Street", zipCode: "94608",
city: "Emeryville", state: "California")
do {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToUpperCamelCase
let encoded = try encoder.encode(address)
print(String(decoding: encoded, as: UTF8.self))
} catch {
print(error)
}
//{"Street":"Apple Bay Street","City":"Emeryville","State":"California","ZipCode":"94608"}
और .convertFromUpperCamelCase
प्रमुख रणनीति के साथ डिकोड करें :
let jsonString = """
{"Street":"Apple Bay Street","City":"Emeryville","State":"California","ZipCode":"94608"}
"""
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromUpperCamelCase
let decoded = try decoder.decode(Address.self, from: Data(jsonString.utf8))
print(decoded)
} catch {
print(error)
}
// Address(street: "Apple Bay Street", zipCode: "94608",
// city: "Emeryville", state: "California")
CodingKeys
एनम के नीचे ; क्या मैं सिर्फ एक कुंजी सूचीबद्ध कर सकता हूं जिसे मैं बदल रहा हूं?