如何在Swift中使用许多唯一键解码嵌套的JSON?

时间:2018-04-30 02:52:02

标签: json swift codable decodable

我的问题是我可以用来解码具有许多不同密钥的JSON的最佳方法是什么?现在,我正在为每一个创建一个var。这似乎是低效/硬编码,我有大约8种不同的菜单来解码。

这是我的JSON :(很久,我知道)

{
  "Brunch": {
    "BEAR FIT": [
      "Savory Tofu, Spinach, Tomato Scramble"
    ], 
    "BEAR FUSION": [
      "Roasted Red & Gold Beets", 
      "Baked Ham", 
      "Parslied Potatoes", 
      "Roasted Zuchhini Squash Medley", 
      "Vegan Celebration Roast", 
      "Steamed Rice", 
      "Brown Rice"
    ], 
    "BEAR NECESSITIES": [
      "Rolled Oatmeal", 
      "Italian Wedding Soup"
    ], 
    "BEAR SWEETS": [
      "Blueberry Muffin", 
      "Cranberry Orange Scone", 
      "Assorted Danish"
    ], 
    "BREAKFAST PLATE": [
      "Hashbrown Tri Patty", 
      "Spiced French Toast", 
      "Breakfast Veggie Patty"
    ], 
    "GOLDEN GRILL": [
      "Waffle Bar Toppings"
    ], 
    "ITALIAN CORNER": [
      "Omelet Bar"
    ], 
    "PASTAS": [
      "Breadsticks", 
      "Pasta", 
      "Whole Wheat Pasta", 
      "Creamy Alfredo Sauce", 
      "Beef Bolognese Sauce"
    ], 
    "SMOOTHIES": [
      "Peach Smoothie"
    ], 
    "SPECIALTY SALADS": [
      "Macaroni Salad"
    ]
  }, 
  "Dinner": {
    "BEAR FIT": [
      "Vegetable Caribbean Blend", 
      "Three Bean Chili", 
      "Brown Rice"
    ], 
    "BEAR FUSION": [
      "Chicken Vindaloo", 
      "Chana Masala", 
      "Brown Rice", 
      "Steamed Rice"
    ], 
    "BEAR NECESSITIES": [
      "Garden Vegetable Soup with Tomato", 
      "Italian Wedding Soup"
    ], 
    "BEAR SWEETS": [
      "Raspberry Sammie", 
      "Chocolate Chunk Brownie", 
      "Pumpkin Pie"
    ], 
    "CAL-ZONE": [
      "Mushroom & Olive Flatbread", 
      "Meat Lovers Pizza", 
      "Pepperoni Pizza"
    ], 
    "GOLDEN GRILL": [
      "Fish Sandwich", 
      "Malibu Burger", 
      "Shoestring Fries"
    ], 
    "PASTAS": [
      "Breadsticks", 
      "Pasta", 
      "Whole Wheat Pasta", 
      "Creamy Alfredo Sauce", 
      "Beef Bolognese Sauce"
    ], 
    "SPECIALTY SALADS": [
      "Macaroni Salad"
    ], 
    "THE BIG C": [
      "Hawaiian BBQ Pork", 
      "Blackened Tilapia with Lemon Pepper", 
      "Teriyaki Tofu", 
      "Steamed Rice", 
      "Suateed Cabbage", 
      "Cinnamon Glazed Carrot"
    ]
  }
}

这是我现在的解析器:

struct WeekendMenu: Decodable {
    struct Brunch: Decodable {
        var BEAR_FIT: [String]
        var BEAR_FUSION: [String]
        var BEAR_NECESSITIES: [String]
        var BEAR_SWEETS: [String]
        var BREAKFAST_PLATE: [String]
        var GOLDEN_GRILL: [String]
        var ITALIAN_CORNER: [String]
        var PASTAS: [String]
        var SMOOTHIES: [String]
        var SPECIALTY_SALADS: [String]
        private enum CodingKeys: String, CodingKey {
            case BEAR_FIT  = "BEAR FIT"
            case BEAR_FUSION  = "BEAR FUSION"
            case BEAR_NECESSITIES  = "BEAR NECESSITIES"
            case BEAR_SWEETS  = "BEAR SWEETS"
            case BREAKFAST_PLATE  = "BREAKFAST PLATE"
            case GOLDEN_GRILL  = "GOLDEN GRILL"
            case ITALIAN_CORNER  = "ITALIAN CORNER"
            case PASTAS  = "PASTAS"
            case SMOOTHIES  = "SMOOTHIES"
            case SPECIALTY_SALADS  = "SPECIALTY SALADS"
        }
    }
    struct Dinner: Decodable {
        //TODO
    }
    var brunch: String
    var dinner: String
    private enum CodingKeys: String, CodingKey {
        case brunch = "Brunch"
        case dinner = "Dinner"
    }
}

1 个答案:

答案 0 :(得分:0)

在这种情况下,我建议将JSON解码为词典[String:[String]]

struct WeekendMenu: Decodable {
    private enum CodingKeys : String, CodingKey { case brunch = "Brunch", dinner = "Dinner" }

    let brunch: [String:[String]]
    let dinner: [String:[String]]
}

枚举词典,对键进行排序以获得相同的顺序

let result = try JSONDecoder().decode(WeekendMenu.self, from: data)
for key in result.brunch.keys.sorted() {
    print(key, result.brunch[key]!)
}
for key in result.dinner.keys.sorted() {
    print(key, result.dinner[key]!)
}

或者编写自定义初始化程序,将字典解码为自定义结构Category,密钥变为name,值变为dishes数组。

struct WeekendMenu: Decodable {
    private enum CodingKeys : String, CodingKey { case brunch = "Brunch", dinner = "Dinner" }

    let brunch: [Category]
    let dinner: [Category]

     init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let brunch = try container.decode([String:[String]].self, forKey: .brunch)
        let brunchKeys = brunch.keys.sorted()
        self.brunch = brunchKeys.map { Category(name: $0, dishes: brunch[$0]!) }
        let dinner = try container.decode([String:[String]].self, forKey: .dinner)
        let dinnerKeys = dinner.keys.sorted()
        self.dinner = dinnerKeys.map { Category(name: $0, dishes: dinner[$0]!) }
    }
}

struct Category {
    let name : String
    let dishes : [String]
}