Swift Json 使用不确定的传入数据解码

Swift Json decoding with unsure incoming data

我正在努力解码 swift 中的一些 Json 数据。

我的后端 api 会 return 我要么是一个 X 数组,要么是一个对象(至少)有一个 属性 名为 X 类型数组的“items”。

我搜索过但没有找到解决方案。你有吗?

struct A: Decodable {
   var items: [X]
   // some other optional properties

   public init(from decoder: Decoder) throws {
       // Sometimes I receive the correct A object
       // Sometimes I only receive the array of X without the surrounding object of type A.
   }
}

更糟糕的是,我必须解码,就像我总是收到类型 A 的对象一样...:[=​​16=]

myObjectOfTypeA = try decoder.decode(A.self, from: data)

大多数时候,我会收到像这样的合适的 A 对象:

{
    "items": 
    [
        {
            "id": 7,
            "startsOn": "2021-03-01",
            "endsOn": "2021-12-31"
        },
        {
            "id": 6,
            "startsOn": "2021-04-19",
            "endsOn": "2022-04-04"
        }
    ],
    "next": null,
    "prev": null,
    "count": 2
}

但有时,我只会收到这样的项目数组:

[
    {
        "id": 7,
        "startsOn": "2021-03-01",
        "endsOn": "2021-12-31"
    },
    {
        "id": 6,
        "startsOn": "2021-04-19",
        "endsOn": "2022-04-04"
    }
]

任何想法将不胜感激,因为我自己显然没有想法...

您只需要尝试解码您的封闭类型项并捕获错误。如果是类型不匹配错误,请尝试再次解码。无需创建自定义解码器:


struct A: Decodable {
   let items: [X]
}

struct X: Decodable {
    let id: Int
    let startsOn: Date
    let endsOn: Date
}

游乐场测试:

let json = """
{
    "items":
    [
        {
            "id": 7,
            "startsOn": "2021-03-01",
            "endsOn": "2021-12-31"
        },
        {
            "id": 6,
            "startsOn": "2021-04-19",
            "endsOn": "2022-04-04"
        }
    ],
    "next": null,
    "prev": null,
    "count": 2
}
"""

let dateFormatter = DateFormatter()
dateFormatter.calendar = .init(identifier: .iso8601)
dateFormatter.locale = .init(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd"

let jsonDecoder = JSONDecoder()
jsonDecoder.dateDecodingStrategy = .formatted(dateFormatter)
let items: [X]
do {
    items = try jsonDecoder.decode(A.self, from: Data(json.utf8)).items
} catch DecodingError.typeMismatch {
    items = try jsonDecoder.decode([X].self, from: Data(json.utf8))
} catch {
    items = []
    print(error)
}
print(items)

它将为两个 json 输入打印以下内容:

[X(id: 7, startsOn: 2021-03-01 03:00:00 +0000, endsOn: 2021-12-31 03:00:00 +0000), X(id: 6, startsOn: 2021-04-19 03:00:00 +0000, endsOn: 2022-04-04 03:00:00 +0000)]