如何正确解析 SWIFT 中的 JSON 对象

Posted

技术标签:

【中文标题】如何正确解析 SWIFT 中的 JSON 对象【英文标题】:How to Parse JSON object in SWIFT properly 【发布时间】:2019-12-09 11:18:08 【问题描述】:

我已尝试解析此 JSON 对象,但无法正常工作。我也没有收到错误消息。

我正在尝试从 API 获取配方详细信息到数组,但我无法使其工作。我可以从控制台看到 API 调用已经成功并且能够打印 json 文件。

请参阅下面的 json 文件、对象类和解析代码。

Json 文件

    
  "recipes" : [
    
      "veryHealthy" : false,
      "preparationMinutes" : 20,
      "vegan" : false,
      "aggregateLikes" : 8,
      "veryPopular" : false,
      "imageType" : "jpg",
      "diets" : [
        "lacto ovo vegetarian"
      ],
      "creditsText" : "BBC Good Food",
      "extendedIngredients" : [
        
          "originalString" : "200g unsalted butter, softened",
          "name" : "unsalted butter",
          "measures" : 
            "metric" : 
              "amount" : 200,
              "unitLong" : "grams",
              "unitShort" : "g"
            ,
            "us" : 
              "unitLong" : "ounces",
              "amount" : 7.0549999999999997,
              "unitShort" : "oz"
            
          ,
          "consitency" : "solid",
          "aisle" : "Milk, Eggs, Other Dairy",
          "meta" : [
            "unsalted",
            "softened"
          ],
          "image" : "butter-sliced.jpg",
          "metaInformation" : [
            "unsalted",
            "softened"
          ],
          "original" : "200g unsalted butter, softened",
          "amount" : 200,
          "originalName" : "unsalted butter, softened",
          "unit" : "g",
          "id" : 1145
        ,
        
          "originalString" : "125g soft brown sugar",
          "name" : "brown sugar",
          "measures" : 
            "us" : 
              "unitLong" : "ounces",
              "unitShort" : "oz",
              "amount" : 4.4089999999999998
            ,
            "metric" : 
              "unitLong" : "grams",
              "unitShort" : "g",
              "amount" : 125
            
          ,
          "consitency" : "solid",
          "aisle" : "Baking",
          "meta" : [
            "soft"
          ],
          "image" : "dark-brown-sugar.png",
          "metaInformation" : [
            "soft"
          ],
          "original" : "125g soft brown sugar",
          "amount" : 125,
          "originalName" : "soft brown sugar",
          "unit" : "g",
          "id" : 19334
        ,
        
          "originalString" : "1 tsp ground cinnamon",
          "name" : "ground cinnamon",
          "measures" : 
            "us" : 
              "unitLong" : "teaspoon",
              "unitShort" : "tsp",
              "amount" : 1
            ,
            "metric" : 
              "unitLong" : "teaspoon",
              "unitShort" : "tsp",
              "amount" : 1
            
          ,
          "consitency" : "solid",
          "aisle" : "Spices and Seasonings",
          "meta" : [

          ],
          "image" : "cinnamon.jpg",
          "metaInformation" : [

          ],
          "original" : "1 tsp ground cinnamon",
          "amount" : 1,
          "originalName" : "ground cinnamon",
          "unit" : "tsp",
          "id" : 1012010
        ,
        
          "originalString" : "1½ tsp vanilla bean paste",
          "name" : "vanilla bean paste",
          "measures" : 
            "us" : 
              "unitLong" : "teaspoons",
              "unitShort" : "tsps",
              "amount" : 1.5
            ,
            "metric" : 
              "unitLong" : "teaspoons",
              "unitShort" : "tsps",
              "amount" : 1.5
            
          ,
          "consitency" : "solid",
          "aisle" : "Gourmet",
          "meta" : [

          ],
          "image" : "molasses.jpg",
          "metaInformation" : [

          ],
          "original" : "1½ tsp vanilla bean paste",
          "amount" : 1.5,
          "originalName" : "vanilla bean paste",
          "unit" : "tsp",
          "id" : 93813
        ,
        
          "originalString" : "1 pineapple, peeled, cut into quarters, core removed, then cut into 2cm slices",
          "name" : "pineapple",
          "measures" : 
            "us" : 
              "unitLong" : "",
              "unitShort" : "",
              "amount" : 1
            ,
            "metric" : 
              "unitShort" : "",
              "unitLong" : "",
              "amount" : 1
            
          ,
          "consitency" : "solid",
          "aisle" : "Produce",
          "meta" : [
            "peeled",
            "cut into quarters, core removed, then cut into 2cm slices"
          ],
          "image" : "pineapple.jpg",
          "metaInformation" : [
            "peeled",
            "cut into quarters, core removed, then cut into 2cm slices"
          ],
          "original" : "1 pineapple, peeled, cut into quarters, core removed, then cut into 2cm slices",
          "amount" : 1,
          "originalName" : "pineapple, peeled, cut into quarters, core removed, then cut into 2cm slices",
          "unit" : "",
          "id" : 9266
        ,
        
          "originalString" : "140g golden caster sugar",
          "name" : "golden brown sugar",
          "measures" : 
            "us" : 
              "unitShort" : "oz",
              "unitLong" : "ounces",
              "amount" : 4.9379999999999997
            ,
            "metric" : 
              "unitLong" : "grams",
              "unitShort" : "g",
              "amount" : 140
            
          ,
          "consitency" : "solid",
          "aisle" : "Baking",
          "meta" : [

          ],
          "image" : "dark-brown-sugar.png",
          "metaInformation" : [

          ],
          "original" : "140g golden caster sugar",
          "amount" : 140,
          "originalName" : "golden caster sugar",
          "unit" : "g",
          "id" : 19334
        ,
        
          "originalString" : "2 large eggs, plus 1 egg white, beaten",
          "name" : "eggs",
          "measures" : 
            "us" : 
              "unitLong" : "larges",
              "unitShort" : "large",
              "amount" : 2
            ,
            "metric" : 
              "unitShort" : "large",
              "amount" : 2,
              "unitLong" : "larges"
            
          ,
          "consitency" : "solid",
          "aisle" : "Milk, Eggs, Other Dairy",
          "meta" : [
            "beaten"
          ],
          "image" : "egg.png",
          "metaInformation" : [
            "beaten"
          ],
          "original" : "2 large eggs, plus 1 egg white, beaten",
          "amount" : 2,
          "originalName" : "eggs, plus 1 egg white, beaten",
          "unit" : "large",
          "id" : 1123
        ,
        
          "originalString" : "1½ tsp baking powder",
          "name" : "baking powder",
          "measures" : 
            "us" : 
              "unitShort" : "tsps",
              "amount" : 1.5,
              "unitLong" : "teaspoons"
            ,
            "metric" : 
              "unitLong" : "teaspoons",
              "unitShort" : "tsps",
              "amount" : 1.5
            
          ,
          "consitency" : "solid",
          "aisle" : "Baking",
          "meta" : [

          ],
          "image" : "white-powder.jpg",
          "metaInformation" : [

          ],
          "original" : "1½ tsp baking powder",
          "amount" : 1.5,
          "originalName" : "baking powder",
          "unit" : "tsp",
          "id" : 18371
        ,
        
          "originalString" : "200g plain flour",
          "name" : "plain flour",
          "measures" : 
            "us" : 
              "unitLong" : "ounces",
              "unitShort" : "oz",
              "amount" : 7.0549999999999997
            ,
            "metric" : 
              "unitLong" : "grams",
              "unitShort" : "g",
              "amount" : 200
            
          ,
          "consitency" : "solid",
          "aisle" : "Baking",
          "meta" : [
            "plain"
          ],
          "image" : "flour.png",
          "metaInformation" : [
            "plain"
          ],
          "original" : "200g plain flour",
          "amount" : 200,
          "originalName" : "plain flour",
          "unit" : "g",
          "id" : 20081
        ,
        
          "originalString" : "75ml whole milk",
          "name" : "whole milk",
          "measures" : 
            "us" : 
              "unitLong" : "fl. ozs",
              "unitShort" : "fl. oz",
              "amount" : 2.536
            ,
            "metric" : 
              "unitLong" : "milliliters",
              "unitShort" : "ml",
              "amount" : 75
            
          ,
          "consitency" : "liquid",
          "aisle" : "Milk, Eggs, Other Dairy",
          "meta" : [
            "whole"
          ],
          "image" : "milk.png",
          "metaInformation" : [
            "whole"
          ],
          "original" : "75ml whole milk",
          "amount" : 75,
          "originalName" : "whole milk",
          "unit" : "ml",
          "id" : 1077
        
      ],
      "cuisines" : [

      ],
      "cheap" : false,
      "ketogenic" : false,
      "sourceUrl" : "https:\/\/www.bbcgoodfood.com\/recipes\/cinnamon-pineapple-upside-down-cake",
      "sustainable" : false,
      "healthScore" : 5,
      "weightWatcherSmartPoints" : 20,
      "sourceName" : "BBC Good Food",
      "whole30" : false,
      "instructions" : "Heat oven to 180C\/160C fan\/gas 4. Put 4 tbsp of the butter into a 22cm springform cake tin and place in the oven to melt. Remove and stir in the brown sugar, cinnamon and  tsp of the vanilla paste. Arrange the pineapple in the buttery sugar mixture, tossing a little to coat. Try to fill all the gaps, so you cant see much of the base.\nIn a mixing bowl, beat the caster sugar and remaining butter using an electric hand whisk for 2-3 mins until light and fluffy. Add the eggs and egg white, one at a time, and the remaining vanilla. Add the baking powder and a pinch of salt, then the flour and milk, beating until they are both incorporated. Beat for 1 min more until smooth.\nSpoon the batter into the pan over the pineapple. Bake for 1 hr, covering with foil if it starts to brown. Leave to rest for 5 mins, then turn out onto a platter and serve warm as a pudding, with crme frache, if you like. Alternatively, leave to cool completely in the tin and serve as a cake.",
      "analyzedInstructions" : [
        
          "steps" : [
            
              "ingredients" : [

              ],
              "number" : 1,
              "step" : "Heat oven to 180C\/160C fan\/gas",
              "equipment" : [
                
                  "name" : "oven",
                  "id" : 404784,
                  "image" : "oven.jpg",
                  "temperature" : 
                    "unit" : "Celsius",
                    "number" : 180
                  
                
              ]
            ,
            
              "ingredients" : [

              ],
              "number" : 2,
              "step" : "Put 4 tbsp of the butter into a 22cm springform cake tin and place in the oven to melt.",
              "equipment" : [
                
                  "id" : 404747,
                  "image" : "cake-pan.png",
                  "name" : "cake form"
                ,
                
                  "id" : 404784,
                  "image" : "oven.jpg",
                  "name" : "oven"
                
              ]
            ,
            
              "ingredients" : [
                
                  "id" : 93813,
                  "image" : "molasses.jpg",
                  "name" : "vanilla paste"
                ,
                
                  "id" : 19334,
                  "image" : "dark-brown-sugar.png",
                  "name" : "brown sugar"
                ,
                
                  "id" : 9266,
                  "image" : "pineapple.jpg",
                  "name" : "pineapple"
                ,
                
                  "id" : 2010,
                  "image" : "cinnamon.jpg",
                  "name" : "cinnamon"
                
              ],
              "number" : 3,
              "step" : "Remove and stir in the brown sugar, cinnamon and  tsp of the vanilla paste. Arrange the pineapple in the buttery sugar mixture, tossing a little to coat. Try to fill all the gaps, so you cant see much of the base.",
              "equipment" : [

              ]
            ,
            
              "length" : 
                "unit" : "minutes",
                "number" : 3
              ,
              "ingredients" : [

              ],
              "number" : 4,
              "step" : "In a mixing bowl, beat the caster sugar and remaining butter using an electric hand whisk for 2-3 mins until light and fluffy.",
              "equipment" : [
                
                  "id" : 405907,
                  "image" : "mixing-bowl.jpg",
                  "name" : "mixing bowl"
                ,
                
                  "id" : 404661,
                  "image" : "whisk.png",
                  "name" : "whisk"
                
              ]
            ,
            
              "ingredients" : [
                
                  "id" : 1123,
                  "image" : "egg.png",
                  "name" : "egg"
                
              ],
              "number" : 5,
              "step" : "Add the eggs and egg white, one at a time, and the remaining vanilla.",
              "equipment" : [

              ]
            ,
            
              "length" : 
                "unit" : "minutes",
                "number" : 1
              ,
              "ingredients" : [
                
                  "id" : 18371,
                  "image" : "white-powder.jpg",
                  "name" : "baking powder"
                ,
                
                  "id" : 20081,
                  "image" : "flour.png",
                  "name" : "all purpose flour"
                ,
                
                  "id" : 1077,
                  "image" : "milk.png",
                  "name" : "milk"
                
              ],
              "number" : 6,
              "step" : "Add the baking powder and a pinch of salt, then the flour and milk, beating until they are both incorporated. Beat for 1 min more until smooth.",
              "equipment" : [

              ]
            ,
            
              "ingredients" : [
                
                  "id" : 9266,
                  "image" : "pineapple.jpg",
                  "name" : "pineapple"
                
              ],
              "number" : 7,
              "step" : "Spoon the batter into the pan over the pineapple.",
              "equipment" : [
                
                  "id" : 404645,
                  "image" : "pan.png",
                  "name" : "frying pan"
                
              ]
            ,
            
              "length" : 
                "unit" : "minutes",
                "number" : 5
              ,
              "ingredients" : [

              ],
              "number" : 8,
              "step" : "Bake for 1 hr, covering with foil if it starts to brown. Leave to rest for 5 mins, then turn out onto a platter and serve warm as a pudding, with crme frache, if you like. Alternatively, leave to cool completely in the tin and serve as a cake.",
              "equipment" : [
                
                  "id" : 404765,
                  "image" : "aluminum-foil.png",
                  "name" : "aluminum foil"
                
              ]
            
          ],
          "name" : ""
        
      ],
      "spoonacularSourceUrl" : "https:\/\/spoonacular.com\/cinnamon-pineapple-upside-down-cake-212615",
      "vegetarian" : true,
      "gaps" : "no",
      "servings" : 8,
      "cookingMinutes" : 65,
      "title" : "Cinnamon pineapple upside-down cake",
      "id" : 212615,
      "image" : "https:\/\/spoonacular.com\/recipeImages\/212615-556x370.jpg",
      "glutenFree" : false,
      "dishTypes" : [
        "dessert"
      ],
      "lowFodmap" : false,
      "winePairing" : 
        "pairingText" : "Cream Sherry, Moscato d'Asti, and Port are my top picks for Cake. A common wine pairing rule is to make sure your wine is sweeter than your food. Delicate desserts go well with Moscato d'Asti, nutty desserts with cream sherry, and caramel or chocolate desserts pair well with port. The NV Johnson Estate Cream Sherry with a 5 out of 5 star rating seems like a good match. It costs about 19 dollars per bottle.",
        "pairedWines" : [
          "cream sherry",
          "moscato dasti",
          "port"
        ],
        "productMatches" : [
          
            "link" : "https:\/\/www.amazon.com\/Johnson-Estate-Cream-Sherry-750\/dp\/B00D3GQSRW?tag=spoonacular-20",
            "score" : 0.85714285714285721,
            "id" : 430626,
            "price" : "$19.49",
            "title" : "NV Johnson Estate Cream Sherry",
            "imageUrl" : "https:\/\/spoonacular.com\/productImages\/430626-312x231.jpg",
            "averageRating" : 1,
            "description" : "Very aromatic with notes of hazelnut, vanilla, and a touch of oak followed by sweet raisins and a touch of yeast. Clean lasting finish. Good now but will reward those allow it to age\"\". A favorite pre-prandial beverage. Consider it with nuts before dinner as an aperitif, or after dinner with dessert, especially chocolates and fruit-based desserts. Also wonderful on cold afternoons, served with biscotti to dip in \"\"Italian-style\"\". \"",
            "ratingCount" : 2
          
        ]
      ,
      "dairyFree" : false,
      "occasions" : [

      ],
      "spoonacularScore" : 37,
      "pricePerServing" : 91.790000000000006,
      "readyInMinutes" : 85
    
  ]

食谱课

struct Recipe 

    let id: Int
    let name: String

    // Recipes will only ever be instantiated in response to the server
    init(json: JSON) 
        self.id = json["id"].intValue
        self.name = json["title"].stringValue

    


解析不起作用的代码。它将返回空数组。

let recipes: [Recipe] = json.arrayValue.map( Recipe(json: $0) )

【问题讨论】:

【参考方案1】:

请仔细阅读 JSON。

recipes 数组位于键 recipes 的(根)字典中

let recipes = json["recipes"].arrayValue.map Recipe(json: $0) 

强烈建议放弃 SwiftyJSON 以支持内置的 Codable 协议。

【讨论】:

【参考方案2】:

我使用ObjectMapper library + JSONExport 用于类 codeGen。

【讨论】:

如果您不知道如何分析 JSON,那么该工具是无关紧要的。而且 Codable 比 ObjectMapper 强大得多。【参考方案3】:

最好的方法是使用 Codable 协议的力量。

我在下面写了游乐场的例子。

import UIKit

// Models
struct Recipe: Codable 
    let id: Int
    let name: String?


struct Response: Codable 
    let recipes: [Recipe]


// Test JSON
let jsonString = """

    "recipes": [
        
            "id": 141892,
            "name": "Codable Recipe"
        ,
        
            "id": 908,
            "name": "JSON Recipe"
        
    ]

"""

// Codable Test Drive
let data = jsonString.data(using: .utf8)!

do 
    let res = try JSONDecoder().decode(Response.self, from: data)
    print("recipes count: \(res.recipes.count)")
 catch 
    print("decode error: \(error)")

控制台输出: 食谱数:2

【讨论】:

以上是关于如何正确解析 SWIFT 中的 JSON 对象的主要内容,如果未能解决你的问题,请参考以下文章

如何解析 JSON 以将其转换为 Swift 中的对象数组?

swift 1.2 中的 JSON 解析问题

如何以正确的方式在 IOS SWIFT 3 中解析 Google 距离矩阵 API JSON

解析 JSON 文件(本地存储),从而快速创建对象数组

使用 Alamofire 解析字典中的 json 对象 [关闭]

我如何使用解码器在swift 4中解析tableview中的json数组