Как декодировать вложенный JSON с множеством уникальных ключей в Swift? - PullRequest
0 голосов
/ 30 апреля 2018

Мои вопросы: какой лучший метод я могу использовать для декодирования JSON, который имеет много разных ключей? Прямо сейчас я создаю переменную для каждого. Это кажется неэффективным / жестким кодированием, и у меня есть около 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 голосов
/ 30 апреля 2018

В этом случае я рекомендую декодировать 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]
}
...