When decoding a Codable struct from JSON, how do you initialize a property not present in the JSON?
You can simply use coding keys, like this:
struct Reminder: Identifiable, Codable {
var id: String = UUID().uuidString
var title: String
var dueDate: Date
var notes: String? = nil
var isComplete: Bool = false
enum CodingKeys: String, CodingKey {
case title
case dueDate
case notes
case isComplete
}
}
That way, the only properties that will be encoded/decoded are the ones that have a corresponding coding key.
Swift 4 Codable decoding json
If your JSON has a structure
{"themes" : [{"title": "Foo", "answer": 1, "question": 2},
{"title": "Bar", "answer": 3, "question": 4}]}
you need an equivalent for the themes
object. Add this struct
struct Theme : Codable {
var themes : [Question]
}
Now you can decode the JSON:
if let decoded = try? JSONDecoder().decode(Theme.self, from: data) {
print("decoded:", decoded)
} else {
print("Not working")
}
The containing Question
objects are decoded implicitly.
Swift Codable JSON parse error with JSONDecoder
You have several mistakes on defining object. For example you have defined id
, msupply
is a integer but they are string. You have defined the volume24
and volume24a
is string but they are not. You need to fix all of these probably thats why you can't parse it.
All wrong defined parameters are id
, mSupply
, volume24
, volume24a
, tSupply
for coin object and for the info
object you need to convert time
to Int
aswell.
Parse JSON from file using Codable swift
You are trying to decode a type of Cities.self
, but your JSON is an array - it starts with "[" and ends with "]". You might want to try declaring the type [Cities].self
in your decoder call.
let jsonDescription = try JSONDecoder().decode([City].self, from: data)
Edit:
@Joakim_Danielson caught an issue, you need to decode the array [City]
and not [Cities]
, because that's what your JSON is (I edited the above line of code accordingly).
But there is another issue: the property coord
in your struct City
is declared as an array [Coordinates]?
, but your JSON does not have an array in the "coord" key - just a single instance.
Try changing your coord
property, make it a type of Coordinate?
.
Using Codable to encode/decode from Strings to Ints with a function in between
For Codable
encoding and decoding that requires custom transformation type stuff, like that, you just need to implement the initializer and encode methods yourself. In your case it would look something like this. It's a bit verbose just to try to get the idea across really clearly.
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
let hexAString: String = try container.decode(String.self, forKey: .hexA)
self.hexA = hexAConversion(from: hexAString)
let hexBString: String = try container.decode(String.self, forKey: .hexB)
self.hexB = hexBConversion(from: hexBString)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
//Assuming you have another set of methods for converting back to a String for encoding
try container.encode(self.name, forKey: .name)
try container.encode(hexAStringConversion(from: self.hexA), forKey: .hexA)
try container.encode(hexBStringConversion(from: self.hexB), forKey: .hexB)
}
Hot to decode JSON data that could and array or a single element in Swift?
Your JSON actually is either a String or an array of Strings. So you need to create a custom decoder to decode and then convert them to Double:
struct Info {
let author, title: String
let tags: [Tags]
let price: [Double]
enum Tags: String, Codable {
case nonfiction, biography, fiction
}
}
extension Info: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
author = try container.decode(String.self, forKey: .author)
title = try container.decode(String.self, forKey: .title)
tags = try container.decode([Tags].self, forKey: .tags)
do {
price = try [Double(container.decode(String.self, forKey: .price)) ?? .zero]
} catch {
price = try container.decode([String].self, forKey: .price).compactMap(Double.init)
}
}
}
Playground testing
let infoData = Data("""
{
"author" : "Mark A",
"title" : "The Great Deman",
"tags" : [
"nonfiction",
"biography"
],
"price" : "242"
}
""".utf8)
do {
let info = try JSONDecoder().decode(Info.self, from: infoData)
print("price",info.price) // "price [242.0]\n"
} catch {
print(error)
}
let infoData2 = Data("""
{
"author" : "Mark A",
"title" : "The Great Deman",
"tags" : [
"nonfiction",
"biography"
],
"price" : [
"242",
"299",
"335"
]
}
""".utf8)
do {
let info = try JSONDecoder().decode(Info.self, from: infoData2)
print("price",info.price) // "price [242.0, 299.0, 335.0]\n"
} catch {
print(error)
}
Related Topics
Show/Hide Password - How to Add This Feature
Using Environmentobject in Watchos
Using Apple's New Audioengine to Change Pitch of Audioplayer Sound
Is Self Captured Within a Nested Function
Detecting iOS Dark Mode Change
Perform a Segue Programmatically
Difference Between Swift's Hash and Hashvalue
Nspredicate with Swift and Core Data
Scroll Uicollectionview to Bottom
Subclassing VS Extension in Swift
How to Attach an Object to Your Camera Position with Arkit Swift
How to Show an Alert from Another Class in Swift
Accessing Self from Instance Properties Which Are Closures
Property Cannot Be Declared Public Because Its Type Uses an Internal Type
Optional Chaining with Swift Strings