Как разобрать JSON, содержащий динамические ключи, используя decodable? - PullRequest
0 голосов
/ 24 октября 2018

Проблема

В настоящее время у меня возникают проблемы с декодированием общих ключей в JSON.Моя текущая реализация принимает 3 ключа первичный, вторичный, третичный.Однако в будущем я хочу, чтобы ключи словарей JSON были общими.Я попытался реализовать аналогичный способ, как указано в этом руководстве: https://benscheirman.com/2017/06/swift-json/. К сожалению, я не могу заставить его работать, и некоторая помощь действительно приветствуется.

Мой вопрос не является дубликатом нижеприведенногоone

Следующий пост обрабатывает совершенно другой уровень родовых "nes": Как работать с полностью динамическими JSON-ответами , поэтому мой вопрос гораздо более лаконичен, чем тот, который рекламирует этот вопроскак и в случае с постом выше ..

текущий JSON

{
  "primary": {
    "color": [3,111,66,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
    }
  },
  "secondary": {
    "color": [11,34,56,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
    }
  },
  "tertiary": {
    "color": [233,222,211,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
    }
  }
}

желаемый / возможный JSON

{
      "SomeKey": {
        "color": [3,111,66,1],
        "font": {
          "name": "UniversLTStd-UltraCn",
          "size": "16"
        }
      },
      "OtherKey": {
        "color": [11,34,56,1],
        "font": {
          "name": "UniversLTStd-UltraCn",
          "size": "16"
        }
      },
      "AnotherKey": {
        "color": [233,222,211,1],
        "font": {
          "name": "UniversLTStd-UltraCn",
          "size": "16"
        }
      }
    }

Декодируемые структуры можно найти здесь: https://pastebin.com/ZYafkDNH

Вопрос

Как я могу перенести текущий код на прием динамических ключей (вместо первичных, вторичных, третичных ...), чтобы мне не приходилось жестко их кодироватьбазовая / корневая структура, которую можно найти в теме сейчас.

Ответы [ 2 ]

0 голосов
/ 24 октября 2018

Поскольку вы, похоже, отвечаете за JSON, я рекомендую изменить структуру на массив и свойство type.

[{"type": "primary",
  "appearance": {
    "color": [3,111,66,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
      }
    }
  },
  {
  "type": "secondary",
  "appearance": {
    "color": [11,34,56,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
      }
    }
  },
  {
  "type": "tertiary",
  "appearance": {
    "color": [233,222,211,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
      }
    }
}]

, которое гораздо проще поддерживать.

Соответствующие структуры имеют вид

struct Theme : Decodable {
    let type : String // could be even a custom enum
    let appearance : Appearance
}

struct Appearance: Decodable {
    let color: [UInt8]
    let font: Font
}

struct Font: Decodable {
    let name, size: String
}

и декодируют JSON в [Theme].self

В противном случае, как рекомендует Sh_Khan, вам необходимо декодировать словарь или написать собственный инициализатор.

0 голосов
/ 24 октября 2018

Вы можете попытаться проанализировать его как словарь [String:Key] вместо жесткого кодирования ключей, тем самым он будет проанализирован, если ключи изменены, но вы должны выполнить некоторую логику внутри приложения, чтобы узнать, какое значение соответствуетуказанный ключ

let res = try? JSONDecoder().decode([String:Key].self, from: jsonData)


struct Key: Codable {
    let color: [Int]
    let font: Font
}

struct Font: Codable {
    let name, size: String
}
...