I’m trying to decode a JSON string in swift but having some weird issues accessing the properties once decoded.
This is the contents of the JSON file that I retrieve from a locally stored JSON file
[
{
"word": "a",
"usage": [
{
"partOfSpeech": "determiner"
}
]
}
]
And this is the code to access the properties of the JSON file
struct WordDictionary : Codable {
var word: String
var usage: [Usage]
}
struct Usage: Codable {
var partOfSpeech: String
}
if let url = Bundle.main.url(forResource: FILE_NAME, withExtension: "json") {
do {
let data = try Data(contentsOf: url)
let decoder = JSONDecoder()
let jsonData = try decoder.decode([WordDictionary].self, from: data)
print(jsonData[0].word) //Outputs "a"
print(jsonData[0].usage) //Outputs "[MyApp.AppDelegate.(unknown context at $102a37f00).(unknown context at $102a38038).Usage(partOfSpeech: "determiner")]"
} catch {
print("error:(error)")
}
}
As you can see, when I try to print(jsonData[0].usage)
I get a series of unknown data messages before I get the “Usage” property. When I print this line I just want to see determiner
, I’m not sure what the preamble about the “unknown context” is all about.
I’m also running this code in didFinishLaunchingWithOptions
function of the AppDelegate
.
I’m not sure what I’m missing. I’ve been trying to find a solution for a few days now and trying different approaches but still can’t get the desired output, any help would be appreciated.
2
Answers
If you want a type to print nicely when you interpolate an instance of it into a string, you need to make it conform to CustomStringConvertible.
This protocol declares one property:
description
and when string interpolation encounters an object that conforms to it, it uses the string returned bydescription
instead.You need something like:
if you want a JSON like* string to print.
An alternative would be to re-encode the object using a
JSONEncoder
and convert the data to aString
. That’s much heavier but might be a better option for more complex objects.*JSON like because things like line feeds and tabs won’t be replaced by escapes and
"
andappearing in the string won’t be escaped.
tl;dr
You are seeing the “unknown context” in the description of the type, because it was defined inside a function. You can solve this by either moving those type definitions outside of the function or implementing your own
CustomStringConvertible
conformance.It’s a matter of where you defined your types.
Consider:
That produces:
That is saying that
Usage
was defined in some unknown context within theAppDelegate
withinMyApp
. In short, it does not know how to represent the hierarchy for types defined within functions.Contrast that with:
Which produces:
You can also add your own
CustomStringConvertible
conformance:Which produces:
Through
CustomStringConvertible
, you can make theprint
format it however you want.