Swift中如何从JSON初始化模型?MVVM场景下取值问题
Hey there! Let's walk through how to properly parse that JSON response into your model, since you're dealing with a nested location object alongside the top-level name field.
First, let's restate your JSON structure clearly to avoid confusion:
{ "data": [ { "name": "a", "location": { "city": "h" } }, {} // Empty object we need to handle gracefully ], "a": {}, "b": {} }
Step 1: Update Your Model's Initializer
Your existing model has city and name properties, so we need to adjust the init?(dictionary: JSONDictionary) method to dig into the nested location dictionary. First, let's make sure we have the JSONDictionary typealias set up (you probably already have this, but just in case):
typealias JSONDictionary = [String: Any] struct YourModel { var city: String! var name: String! init?(dictionary: JSONDictionary) { // 1. Grab the top-level "name" field first guard let name = dictionary["name"] as? String else { // If name is missing, we can't initialize the model (adjust if you want optional values) return nil } // 2. Dig into the nested "location" object to get "city" guard let locationDict = dictionary["location"] as? JSONDictionary, let city = locationDict["city"] as? String else { // If location or city is missing, bail on initialization return nil } // Assign values to the model properties self.name = name self.city = city } }
Step 2: Parse the Full JSON Response
Once your model's initializer is ready, you can parse the entire response by targeting the data array, then converting each item into your model. We'll use compactMap to automatically filter out any items that fail initialization (like that empty object in your JSON example):
// Assume `responseDict` is the full JSON dictionary you get from the API if let dataArray = responseDict["data"] as? [JSONDictionary] { // Convert each dictionary in the array to a YourModel instance let parsedModels = dataArray.compactMap { YourModel(dictionary: $0) } // Now `parsedModels` contains only the valid entries (the first item in your JSON example) // You can use this array in your ViewModel to update the UI! }
Optional: Handling Optional Values
If you want your model to allow missing name or city (instead of failing initialization entirely), you can switch your properties to optional types and adjust the initializer:
struct YourModel { var city: String? var name: String? init(dictionary: JSONDictionary) { self.name = dictionary["name"] as? String // Safely unwrap the location dictionary to get city let locationDict = dictionary["location"] as? JSONDictionary self.city = locationDict?["city"] as? String } }
This way, even the empty object in your JSON will create a model with nil values for name and city, instead of being filtered out. Choose this approach if you need to handle partial data!
内容的提问来源于stack exchange,提问作者meggie

