Расшифровка JSON без ключей в Swift 4

Я использую API, который возвращает этот довольно ужасный JSON:

[
  "A string",
  [
    "A string",
    "A string",
    "A string",
    "A string",
    …
  ]
]

Я пытаюсь декодировать вложенный массив с помощью JSONDecoder, но у него нет ни одного ключа, и я действительно не знаю, с чего начать... У вас есть идеи?

Большое спасибо!

3 ответа

Решение

Если структура остается прежней, вы можете использовать этот подход Decodable.

Сначала создайте декодируемую модель следующим образом:

struct MyModel: Decodable {
    let firstString: String
    let stringArray: [String]

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        firstString = try container.decode(String.self)
        stringArray = try container.decode([String].self)
    }
}

Или, если вы действительно хотите сохранить структуру JSON, вот так:

struct MyModel: Decodable {
    let array: [Any]

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        let firstString = try container.decode(String.self)
        let stringArray = try container.decode([String].self)
        array = [firstString, stringArray]
    }
}

И используйте это так

let jsonString = """
["A string1", ["A string2", "A string3", "A string4", "A string5"]]
"""
if let jsonData = jsonString.data(using: .utf8) {
    let myModel = try? JSONDecoder().decode(MyModel.self, from: jsonData)
}

Это немного интересно для декодирования.

У вас нет key, Таким образом, это устраняет необходимость в обертке struct,

Но посмотрите на внутренние типы. Вы получаете смесь String а также [String] типы. Таким образом, вам нужно что-то, что имеет дело с этим типом смеси. Вам понадобится enum точнее.

// I've provided the Encodable & Decodable both with Codable for clarity. You obviously can omit the implementation for Encodable
enum StringOrArrayType: Codable {
    case string(String)
    case array([String])

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        do {
            self = try .string(container.decode(String.self))
        } catch DecodingError.typeMismatch {
            do {
                self = try .array(container.decode([String].self))
            } catch DecodingError.typeMismatch {
                throw DecodingError.typeMismatch(StringOrArrayType.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Encoded payload conflicts with expected type"))
            }
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .string(let string):
            try container.encode(string)
        case .array(let array):
            try container.encode(array)
        }
    }
}

Процесс декодирования:

let json = """
[
  "A string",
  [
    "A string",
    "A string",
    "A string",
    "A string"
  ]
]
""".data(using: .utf8)!

do {
    let response = try JSONDecoder().decode([StringOrArrayType].self, from: json)
    // Here, you have your Array
    print(response) // ["A string", ["A string", "A string", "A string", "A string"]]

    // If you want to get elements from this Array, you might do something like below
    response.forEach({ (element) in
        if case .string(let string) = element {
            print(string) // "A string"
        }
        if case .array(let array) = element {
            print(array) // ["A string", "A string", "A string", "A string"]
        }
    })
} catch {
    print(error)
}

Возможным решением является использование JSONSerialization, тогда вы можете просто копаться в таком json, делая так:

import Foundation

let jsonString = "[\"A string\",[\"A string\",\"A string\", \"A string\", \"A string\"]]"
if let jsonData = jsonString.data(using: .utf8) {
    if let jsonArray = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [Any] {
        jsonArray.forEach {
            if let innerArray = $0 as? [Any] {
                print(innerArray) // this is the stuff you need
            }
        }
    }
}
Другие вопросы по тегам