मैन्युअल रूप से कोडिंग कुंजी को अनुकूलित करना
आपके उदाहरण में, आपको स्वतः-जेनरेट की गई अनुरूपता मिल रही है 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 enumCodingKeystypealiasEncodableDecodable - और प्रकार जो मैन्युअल रूप से एक (नाम , सीधे या एक के माध्यम से ) प्रदान करते हैं, जिनके मामले नाम से 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जो इस सरणी में अंतिम कुंजी को बदल देगा।
उदाहरण के लिए, UpperCamelCaseJSON कुंजियाँ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एनम के नीचे ; क्या मैं सिर्फ एक कुंजी सूचीबद्ध कर सकता हूं जिसे मैं बदल रहा हूं?