Join Steven Lipton for an in-depth discussion in this video Read JSON files, part of iOS Development Tips Weekly.
- [Instructor] A very popular data file is JSON. Apple uses it in Xcode and for remote notifications. As developers, we may need to read JSON files with our code, and translate them into usable objects in Swift. With the JSONDecoder, it's easier than pronouncing JSON, or is it JSON? I'll start with this skeleton app I made. On lines eight through 18, you'll see some JSON code. I enclosed it with the new Swift triple quote string delimiters for multi-line text.
For the coders to work this is supposed to be of type Data, which I can set up with the data method, encoding it to UTF8. Now I'm not going to give you a full lesson on JSON, but here's a brief summary for the uninitiated. This is a collection of objects, with a string key and a value, much like a dictionary in Swift. The braces encase the object, the first string is the key, and then we have a value.
Values can be of most basic data types, such as strings, integers, floats, bools, and doubles. You can also use arrays like I did here for the locations. The real power of JSON is making objects within objects. I can even take objects and make them arrays, like I did with the menu items. So I have, for example, one menu item here for the bestMenuItem, and I used an object which is item and price, and I used the same item and price object down here for an array of menu items.
While JSON code looks like a dictionary, I'll represent this with a struct. I'm going to call this one Restaurant. Each key is a variable here, but with one very important difference. I added a Codable protocol, making the struct able to code and decode the JSON File. For the MenuItems array, and the bestMenuItem, I used a type MenuItem.
I coded that above also as a Codable struct. Scroll down a little bit and you'll see two skills and functions I made for you. I'll do the encode first. I'll need an encoder object which comes from the class JSONEncoder. So I'll type let encoder equal JSON, and there is the encoder. And I use this encoder to encode the data object into JSON.
This throws an error, so I'll use a try here. Data equals try, let me use question mark for this one. Encoder dot encode, and I'm going to put restaurant. That's all there is for this, you get a data object you can send out somewhere. The decoding is just as easy, though I'll add a wrinkle here. First you get the decoder instance.
So we'll do let decoder equal J-S-O-N Decoder. Since decode throws errors too, I'll add this one to a do catch. Do, inside I'll do a try. Try restaurant equals decoder dot decode.
And I have two parameters here. The first one is a type, which is the struct, so I'm going to use restaurant dot self to give me the type, and from, and that'll be from the data. Now we're going to catch the error, and print an error message this time, so I'm going to do catch let error as NSError, and then do a print statement, error reading JSON file.
Quote here so this will work right. And then I'm going to just put error, localizedDescription. There we go. So now we've encoded both the encoder and decoder in very few lines of code. If you go to the bottom of a playground, you'll see I gave you an object Brandi. Add these lines to encode, then decode the struct.
So I'm going to do let restaurant equal encodeJSON for a type restaurant, which is Brandi, which is the home of the Pizza Margherita, and then I'm going to print the restaurant, which I have a nice little function up here to do the printing for me, which I gave you already, and that's going to take the decode as its parameter.
D-E-C-O, decodeJSON, and I'm going to use the restaurant data. Go ahead and run that, and you'll see on the bottom it reads and then writes back out that pizzeria. And like I said, it says to try the Pizza Margherita, which it's famous for. Alright, now one more thing I want to try here.
On line 91, do another print restaurant. This time we'll do it with the myJSON, so we have to decode JSON, and the data will be myJSON from way up top here, okay. Now go ahead and run that, and you find you get an error. Data could not be read because it is missing. Okay, so we've got an issue here.
The issue, if you look back up here, is the key bestMenuItem has underscores, where the restaurant variable is bestMenuItem. So you have a mismatch to your keys. By default the struct and the JSON default to something like this, and it'll be whatever you make the variable. Now, sometimes you'll have the case where this is not the same, and that's what this down here is for, the CodingKeys.
You don't need it if everything matches perfectly like I have here in MenuItem, but you do need it if you have a case like this one where it's spelled differently, or it's got a different key name. So now I've changed bestMenuItem here, and in the CodingKeys, I now know that bestMenuItem camelback has got the one with the underscores. I go ahead and run this, and now it works for the Huli Pizza Company.
There's a lot more in JSON and what you can do. For more I would check out the Worldwide Developer Conference 2017 video, What's New In Foundation, at about the 23 minute point where they start talking about this all.