2017-07-20 11 views
17

मेरे पास एक संरचना है जो स्विफ्ट 4 के Codable लागू करती है। क्या उस संरचना को एक शब्दकोश में एन्कोड करने का एक सरल अंतर्निहित तरीका है?मैं एक शब्दकोश में एन्कोड करने के लिए स्विफ्ट के कोडेबल का उपयोग कैसे कर सकता हूं?

let struct = Foo(a: 1, b: 2) 
let dict = something(struct) 
// now dict is ["a": 1, "b": 2] 

उत्तर

35

आप डेटा के स्थानांतरण का एक सा कोई आपत्ति नहीं है आप कुछ इस तरह इस्तेमाल कर सकते हैं चारों ओर:

extension Encodable { 
    func asDictionary() throws -> [String: Any] { 
    let data = try JSONEncoder().encode(self) 
    guard let dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] else { 
     throw NSError() 
    } 
    return dictionary 
    } 
} 

या एक वैकल्पिक varient

extension Encodable { 
    var dictionary: [String: Any]? { 
    guard let data = try? JSONEncoder().encode(self) else { return nil } 
    return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? [String: Any] } 
    } 
} 

मान लिया जाये कि FooCodable या वास्तव में Encodable के अनुरूप है तो आप यह कर सकते हैं।

let struct = Foo(a: 1, b: 2) 
let dict = try struct.asDictionary() 
let optionalDict = struct.dictionary 

आप अन्य तरीके से (init(any)) जाना चाहते हैं, मैं एक पुस्तकालय CodableFirebase बनाएं जिसका नाम है इस Init an object conforming to Codable with a dictionary/array

3

मुझे यकीन है कि अगर यह सबसे अच्छा तरीका है नहीं कर रहा हूँ, लेकिन आप निश्चित रूप से की तरह कुछ कर सकते हैं:

struct Foo: Codable { 
    var a: Int 
    var b: Int 

    init(a: Int, b: Int) { 
     self.a = a 
     self.b = b 
    } 
} 

let foo = Foo(a: 1, b: 2) 
let dict = try JSONDecoder().decode([String: Int].self, from: JSONEncoder().encode(foo)) 
print(dict) 
+1

यह केवल उसी तरह के सभी गुणों के साथ संरचनाओं के लिए काम करेगा –

0

मैं एक त्वरित gist लिखा था (Codable प्रोटोकॉल का उपयोग नहीं) इस संभालने के लिए। सावधान रहें, यह किसी भी मूल्य को टाइप-चेक नहीं करता है और एन्कोडेबल मानों पर रिकर्सिव रूप से काम नहीं करता है।

class DictionaryEncoder { 
    var result: [String: Any] 

    init() { 
     result = [:] 
    } 

    func encode(_ encodable: DictionaryEncodable) -> [String: Any] { 
     encodable.encode(self) 
     return result 
    } 

    func encode<T, K>(_ value: T, key: K) where K: RawRepresentable, K.RawValue == String { 
     result[key.rawValue] = value 
    } 
} 

protocol DictionaryEncodable { 
    func encode(_ encoder: DictionaryEncoder) 
} 
-2

यह सोचने के लिए आओ, प्रश्न, सामान्य मामले में एक जवाब नहीं है के बाद से Encodable उदाहरण इस तरह के एक सरणी के रूप में कुछ एक शब्दकोश में serializable नहीं, हो सकता है:

let payload = [1, 2, 3] 
let encoded = try JSONEncoder().encode(payload) // "[1,2,3]" 

इसके अलावा, मैंने something similar as a framework लिखा है।

0

let dict = try JSONSerialization.jsonObject(with: try JSONEncoder().encode(struct), options: []) as? [String: Any]

6

पर एक नज़र डालें और यह प्रारंभिक उद्देश्य के साथ इसका इस्तेमाल करने के लिए था है फायरबेस डेटाबेस, लेकिन वास्तव में आपको इसकी आवश्यकता होती है: यह JSONDecoder की तरह एक शब्दकोश या किसी अन्य प्रकार का निर्माण करता है लेकिन आपको दूसरे उत्तरों में जैसे डबल रूपांतरण करने की आवश्यकता नहीं है। तो यह कुछ ऐसा दिखाई देगा:

import CodableFirebase 

let model = Foo(a: 1, b: 2) 
let dict = try! FirebaseEncoder().encode(model) 
0

मैं निश्चित रूप से लगता है कि सिर्फ Codable उपयोग करने के लिए शब्दकोशों से/सांकेतिक शब्दों में बदलना करने में सक्षम होने में कुछ मूल्य है कि, कभी मार JSON/plists के इरादे/जो कुछ भी बिना। बहुत सारे एपीआई हैं जो आपको बस एक शब्दकोश वापस देते हैं, या एक शब्दकोश की उम्मीद करते हैं, और अंतहीन बॉयलरप्लेट कोड लिखने के बिना स्विफ्ट structs या ऑब्जेक्ट्स के साथ आसानी से उन्हें बदलने में सक्षम होना अच्छा लगता है।

मैं फाउंडेशन JSONEncoder.swift स्रोत (जो वास्तव में शब्दकोश एन्कोडिंग/डिकोडिंग को आंतरिक रूप से लागू करता है, पर आधारित कुछ कोड के साथ खेल रहा है, लेकिन इसे निर्यात नहीं करता है)।

कोड यहाँ पाया जा सकता है: https://github.com/elegantchaos/DictionaryCoding

यह अभी भी काफी किसी न किसी तरह है, लेकिन मैं इसे थोड़ा विस्तार किया है ताकि, उदाहरण के लिए, यह चूक के साथ मान अनुपलब्ध जब डिकोडिंग में भर सकते हैं।

संबंधित मुद्दे

 संबंधित मुद्दे