I'm playing with the New York Times API and am getting the message
typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 3", intValue: 3), CodingKeys(stringValue: "multimedia", intValue: nil)], debugDescription: "Expected to decode Array but found a string/data instead.", underlyingError: nil))
This happens when the multimedia part of the JSON is a string rather than an array: similar to this SO question:
Swift Codable expected to decode Dictionary<String, Any>but found a string/data instead
So I decided to make a minimum example.
With article
public struct Article : Codable {
var abstract: String?
var thumbnail_standard: String?
var multimedia: [Multimedia]?
var title: String?
var url: URL?
private enum CodingKeys: String, CodingKey {
case abstract = "abstract"
case multimedia = "multimedia"
case thumbnail_standard = "thumbnail_standard"
case title = "title"
case url = "url"
}
}
and multimedia
struct Multimedia: Codable {
var url: String?
private enum CodingKeys: String, CodingKey {
case url = "url"
}
}
I can use JSON string
let jsonString = """
{
"slug_name": "30dc-emoluments",
"section": "U.S.",
"subsection": "Politics",
"title": "Congressional Democrats’ Lawsuit Examining Trump’s Private Business Can Proceed, Federal Judge Says",
"abstract": "The decision is at least a temporary victory for the president’s critics who say he is willfully flaunting constitutional bans.",
"url": "https://www.nytimes.com/2019/04/30/us/politics/trump-emoluments-clauses.html",
"byline": "By SHARON LaFRANIERE",
"thumbnail_standard": "https://static01.nyt.com/images/2019/04/19/world/30dc-emoluments/30dc-emoluments-thumbStandard.jpg",
"item_type": "Article",
"source": "The New York Times",
"updated_date": "2019-04-30T22:09:45-04:00",
"created_date": "2019-04-30T21:56:05-04:00",
"published_date": "2019-04-29T20:00:00-04:00",
"first_published_date": "2019-04-30T21:54:34-04:00",
"material_type_facet": "News",
"kicker": null,
"subheadline": null,
"des_facet": "",
"org_facet": [
"Democratic Party",
"Constitution (US)",
"Justice Department",
"Trump International Hotel (Washington, DC)"
],
"per_facet": [
"Sullivan, Emmet G",
"Trump, Donald J"
],
"geo_facet": "",
"related_urls": [
{
"suggested_link_text": "Appeals Court Judges Appear Skeptical of Emoluments Case Against Trump",
"url": "https://www.nytimes.com/2019/03/19/us/politics/trump-emoluments-lawsuit.html"
},
{
"suggested_link_text": "Democrats in Congress Sue Trump Over Foreign Business Dealings",
"url": "https://www.nytimes.com/2017/06/14/us/politics/democrats-in-congress-to-sue-trump-over-foreign-business-dealings.html"
}
],
"multimedia": [
{
"url": "https://static01.nyt.com/images/2019/04/19/world/30dc-emoluments/30dc-emoluments-thumbStandard.jpg",
"format": "Standard Thumbnail",
"height": 75,
"width": 75,
"type": "image",
"subtype": "photo",
"caption": "The Trump International Hotel in Washington.",
"copyright": "Gabriella Demczuk for The New York Times"
},
{
"url": "https://static01.nyt.com/images/2019/04/19/world/30dc-emoluments/30dc-emoluments-articleInline.jpg",
"format": "Normal",
"height": 130,
"width": 190,
"type": "image",
"subtype": "photo",
"caption": "The Trump International Hotel in Washington.",
"copyright": "Gabriella Demczuk for The New York Times"
},
{
"url": "https://static01.nyt.com/images/2019/04/19/world/30dc-emoluments/30dc-emoluments-mediumThreeByTwo210.jpg",
"format": "mediumThreeByTwo210",
"height": 140,
"width": 210,
"type": "image",
"subtype": "photo",
"caption": "The Trump International Hotel in Washington.",
"copyright": "Gabriella Demczuk for The New York Times"
},
{
"url": "https://static01.nyt.com/images/2019/04/19/world/30dc-emoluments/30dc-emoluments-mediumThreeByTwo440.jpg",
"format": "mediumThreeByTwo440",
"height": 293,
"width": 440,
"type": "image",
"subtype": "photo",
"caption": "The Trump International Hotel in Washington.",
"copyright": "Gabriella Demczuk for The New York Times"
}
]
}
"""
just fine with the code:
if let data = jsonString.data(using: .utf8)
{
let decoder = JSONDecoder()
let result = try? decoder.decode(Article.self, from: data)
print(result)
}
However the following JSON string is decoded as nill:
let jsonString = """
{
"slug_name": "01a3_quote-web",
"section": "Today’s Paper",
"subsection": "",
"title": "Quotation of the Day: Who Killed Atlanta’s Children? Retesting Evidence After 40 Years",
"abstract": "Quotation of the Day for Wednesday, May 1, 2019.",
"url": "https://www.nytimes.com/2019/04/30/todayspaper/quotation-of-the-day-who-killed-atlantas-children-retesting-evidence-after-40-years.html",
"byline": "",
"thumbnail_standard": "",
"item_type": "Article",
"source": "The New York Times",
"updated_date": "2019-04-30T21:26:36-04:00",
"created_date": "2019-04-30T21:26:36-04:00",
"published_date": "2019-04-29T20:00:00-04:00",
"first_published_date": "2019-04-30T21:25:06-04:00",
"material_type_facet": "Quote",
"kicker": null,
"subheadline": null,
"des_facet": "",
"org_facet": "",
"per_facet": "",
"geo_facet": "",
"related_urls": null,
"multimedia": ""
}
"""
Even though I made the properties in my objects optional, used .self in the decoder.decode method.
How can I get the second JSON string to decode?