如何使用前缀解码动态密钥

问题描述 投票:0回答:1

我想将 strIngredient1、strIngredient2、strIngredient3 解码为数组,并将 strMeasure1、strMeasure2、strMeasure3 解码为单独的数组。我们如何使用可解码和编码密钥来做到这一点。我有一个符合可解码协议的对象和一个函数public init(来自解码器:Decoder)

{
  "meals": [
    {
      "idMeal": "53049",
      "strMeal": "Apam balik",
      "strDrinkAlternate": null,
      "strCategory": "Dessert",
      "strArea": "Malaysian",
      "strInstructions": "Mix milk, oil and egg together. Sift flour, baking powder and salt into the mixture. Stir well until all ingredients are combined evenly.\r\n\r\nSpread some batter onto the pan. Spread a thin layer of batter to the side of the pan. Cover the pan for 30-60 seconds until small air bubbles appear.\r\n\r\nAdd butter, cream corn, crushed peanuts and sugar onto the pancake. Fold the pancake into half once the bottom surface is browned.\r\n\r\nCut into wedges and best eaten when it is warm.",
      "strMealThumb": "https://www.themealdb.com/images/media/meals/adxcbq1619787919.jpg",
      "strTags": null,
      "strYoutube": "https://www.youtube.com/watch?v=6R8ffRRJcrg",
      "strIngredient1": "Milk",
      "strIngredient2": "Oil",
      "strIngredient3": "Eggs",
      "strIngredient4": "Flour",
      "strIngredient5": "Baking Powder",
      "strIngredient6": "Salt",
      "strIngredient7": "Unsalted Butter",
      "strIngredient8": "Sugar",
      "strIngredient9": "Peanut Butter",
      "strIngredient10": "",
      "strIngredient11": "",
      "strIngredient12": "",
      "strIngredient13": "",
      "strIngredient14": "",
      "strIngredient15": "",
      "strIngredient16": "",
      "strIngredient17": "",
      "strIngredient18": "",
      "strIngredient19": "",
      "strIngredient20": "",
      "strMeasure1": "200ml",
      "strMeasure2": "60ml",
      "strMeasure3": "2",
      "strMeasure4": "1600g",
      "strMeasure5": "3 tsp",
      "strMeasure6": "1/2 tsp",
      "strMeasure7": "25g",
      "strMeasure8": "45g",
      "strMeasure9": "3 tbs",
      "strMeasure10": " ",
      "strMeasure11": " ",
      "strMeasure12": " ",
      "strMeasure13": " ",
      "strMeasure14": " ",
      "strMeasure15": " ",
      "strMeasure16": " ",
      "strMeasure17": " ",
      "strMeasure18": " ",
      "strMeasure19": " ",
      "strMeasure20": " ",
      "strSource": "https://www.nyonyacooking.com/recipes/apam-balik~SJ5WuvsDf9WQ",
      "strImageSource": null,
      "strCreativeCommonsConfirmed": null,
      "dateModified": null
    }
  ]
}
ios swift decode
1个回答
0
投票

这就是我要做的,与评论者有点不同。我首先为两个编号字段创建自定义

CodingKey
实现:

enum MealNumberedFieldKey {
    case ingredients(Int)
    case measurements(Int)
}

extension MealNumberedFieldKey: CodingKey {
    var intValue: Int? { nil }

    init?(intValue: Int) {
        return nil
    }

    init?(stringValue: String) {
        var string = stringValue
        if string.hasPrefix("strIngredient") {
            string.removeFirst(13)
            guard let number = Int(string) else { return nil }
            self = .ingredients(number)
        } else if string.hasPrefix("strMeasure") {
            string.removeFirst(10)
            guard let number = Int(string) else { return nil }
            self = .measurements(number)
        } else {
            return nil
        }
    }

    var stringValue: String {
        switch self {
        case .ingredients(let number):
            return "strIngredient\(number)"
        case .measurements(let number):
            return "strMeasure\(number)"
        }
    }
}

然后我将使用两个解码容器编写一个自定义

init(from decoder:)
函数,一个使用正常编码键,另一个使用自定义编码键:

struct Meal: Decodable {
    let idMeal: String
    let strMeal: String
    // ...
    let ingredients: [String]
    let measurements: [String]

    enum CodingKeys: String, CodingKey {
        case idMeal
        case strMeal
    }

    init(from decoder: any Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.idMeal = try container.decode(String.self, forKey: .idMeal)
        self.strMeal = try container.decode(String.self, forKey: .strMeal)
        // ...

        let numberedContainer = try decoder.container(keyedBy: MealNumberedFieldKey.self)
        self.ingredients = try (1...20).map { number in
            try numberedContainer.decode(String.self, forKey: .ingredients(number))
        }
        self.measurements = try (1...20).map { number in
            try numberedContainer.decode(String.self, forKey: .measurements(number))
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.