Codable, Decodable, and Encodable in Swift | Continued Learning #21

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right welcome back everyone i'm nick this channel is swiffle thinking where we cover everything is swift and swift ui related and before we begin i first want to thank all of you who are leaving amazing comments on my videos i am super appreciative you guys make it so much more enjoyable for me to actually bring out and make this content so thank you all of you who are watching and following along and with that said in this video we're going to tackle the codable protocol so although codepoll is extremely easy to implement there's actually a lot going on under the hood that you probably didn't know about so in this video we're gonna use the codeable protocol but before we do we're actually gonna look at everything that's happening behind the scenes because that's really what is more important and what you should know as the developer now the reason we even need this codable protocol is so that we can decode and encode our data basically what that means is when we download data from the internet it doesn't come in a data form that we can actually use we need to decode that data into the data structure that we have in our app so first we're going to learn how to decode data from json data on the internet to data that we can use in our app and then we're going to learn how we can do the reverse and we can take the data in our app and we can encode it to send it back out to the internet as json data we're going to then wrap up by actually using the codeable protocol which includes a decoding and encoding all done for us behind the scenes and the reason we're doing this is because in the next video we are finally ready to start downloading data from the internet so hope you guys are excited i hope this video helps you and let's jump into xcode and take a look all right welcome back everyone i'm back in our xcode project as always let's right click on the navigator create a new file this will be a swift ui view and we're going to call this one codable boot camp go ahead and click create let's click resume on the canvas and let's get started and in the last video we learned how to use escape enclosures and the point of that was so that we can get returned data when we go out and download data from a database or from the internet so we're building up to actually being able to download data and then use it in our app but when we download data from the internet it's not in a form that we can actually put directly into our app we first need to decode that data from whatever data type it is in which is usually json data and then convert it into something that we can actually use locally so before we actually download data from the internet i want to introduce you guys and explain what the codable protocol is because that's what we use to convert that data into something that we can actually use so let's start out this view by creating a view model as we often do so let's create a class let's call this codeableviewmodel let's make it conform to observable object and open the brackets let's initialize this in our view with an at state object var vm for view model and we'll set it equal to the codable view model all right we're going to create a model as well so this is our view model this is our view and then we're going to create a model to complete the mvvm setup and again if you don't know what mvvm architecture is i've covered it in the last playlist where we did a to-do app i've also covered it in a bunch of videos in this playlist so you guys should be getting a little familiar with this now and for our struct let's maybe pretend like we have an app where we have customers so we'll create a model for the customer so we'll create a struct we'll call it customer model we'll open the brackets and every customer is going to have a name so we'll say let name of type string we'll pretend like every customer has maybe a certain number of points in our system so we'll say let points of type int and maybe our customers have the option of being premium customers so we'll say let is premium of type bool this will just be true or false whether or not they are premium i want to use this in a for each in our view so let's make this conform to identifiable i've covered identifiable previously so you should be aware of it if not go check out the earlier videos in this playlist as i always do in my playlists the videos are building on top of each other so they're meant to be watched in order because i don't want to be throwing in protocols like this identifiable before you actually know what it is all right so to conform to identifiable we just do let id and normally i set this equal to a random id when we use uuid open close parenthesis dot string but when we are downloading stuff from the internet chances are we're going to get that id from the internet we're not going to actually create a random id locally so because of that we're going to create an id and it will just be of type string so when we create customer models we will actually add our id in manually all right now that we have the model let's first set one up in the view and get it all connected so in our view model we'll create an at published var we'll call this customer of type customer model we'll make it optional and for right now for one second let's set this equal to customer model and let's give it an id a of one a name i'll just do nick points five premium true let's just put this customer on the screen quickly so down on our screen let's create a v stack let's give it some spacing of 20 and i don't really care what this screen looks like i just want to put the data on the screen so we'll say if let customer equals vm.customer because remember we made this customer optional so the chance that there is none so here we're just checking that there is a customer and then we're going to put the text we'll do customer dot id i'm just going to copy this paste it four times we'll do customer dot uh what else do we have name customer.points and this points is an integer so we can just convert it to a string with the backslash open close parentheses and then finally we have dot is premium and i can convert this to a string with a dot description if i click resume we should at least see our data on the screen now all right so again i don't really care what this looks like it doesn't look very good but we do see that our data is pulling through and that's all that matters so to start i'm going to actually set our customer this optional customer variable equal to nil if we click resume we can see that nothing is going to pull through because there is no customer yet so once we update this customer it should show up on our screen all right so in our view model we're going to create an init and then we're going to create a function called func get data let's create another func called func get json data open close parenthesis open the brackets and the reason we're going to add this get json data is to simulate uh getting data that we're actually getting from the internet because in a real app this function would probably actually be download from the internet and that function would return us some sort of data but we're just going to create some mock data because we're not worried about downloading from the database just yet we're going to do that in the next video so this download data is actually going to return data and when we download from the internet there's always a chance that it fails maybe it doesn't actually get the data that we want so we're going to make it optional and we're going to do right now real quick is not something you're going to actually have to do in your app but we're just going to create that fake json data so to create json data we we can say let json data equals and we'll use json serialization dot data and we have this option here data with json object and options now the options we're not going to add so let's just open and close the square brackets to make that blank and then we need some sort of object that we want to convert into json data before we do that we're getting an error message that the call can throw but it's not marked with try so we're just going to use try with a question mark because it's going to try to do this but it's okay if it fails and this question mark just means that this json will also be optional so if i hold down json click on this we can see that the data is optional and that's the same return type that we want here so of course we can return json data afterwards all right and the last thing we need is an actual json object that we will convert into json data so to do that we're going to create a dictionary we're going to say let dictionary of type and it'll be in a it'll be a dictionary of string colon any and we'll set it equal to so i'm going to use the exact same names that we put up in our model as well so we'll do id colon and this also needs to be a string so we'll just make it one two three four five comma let's do name colon let's make it joe comma we're gonna do points colon and remember points is an integer so we'll just give this number 5 and then we'll do is premium colon and this is a boolean so we'll make it true we're going to take this dictionary and we're just going to put it into this with json object so again we don't really need to do this in our actual apps we're just going to make some fake data convert it into json data and then return it into our app so in our get data call we're going to say let data equals get json data and this is optional as we see here so let's just do a guard let statement so we'll do else and then we'll just return and we'll just return in an actual app and in the next video we're going to want to maybe print something out or do something if we fail to get the data but for our purposes right now we know this is going to succeed because we can because we're setting up the data ourselves so now that we have this data i first want to print json data colon then i'm going to print out the data i just want to do that so you guys can see what this is actually doing it's converting this into json data so now that we have this let's open up the navigator let's take our view which is decodable boot camp view i'm going to go into the app.swift file where our at main call is let's make this the first view in our app let's click a simulator i'm going to use the iphone 12 and let's run our app on the simulator all right so when my app loads it's just a blank screen because we don't have anything on the screen we didn't actually load any data yet but i get a printout in the console down here that we get the json data and it is 55 bytes so obviously this 55 bytes is not something that we can use in our app but this is how the data actually comes when we download it from the internet it comes in these bytes so we need to decode this data into something that is actually usable and just to iterate on what this is i'm going to quickly convert this into a string so we'll say let json string equals and i'm just going to create a string from it quickly we'll do with the data completion here so there's you can you can create a string from a data i'll pass in our data and encoding will be dot utf-8 all right and then i'll just print out the json string just to show you guys what this actually is so let's print so let's run the simulator one more time it's going to open up here and we get this printout of the 55 bytes and then we get a weird-looking json string which has all of the data that we included right we have the id the name the points but it's in this very funky looking string so obviously this again is not something that we can directly use into our app it's got brackets it's got slashes this is good data but it is not as comfortable and usable as a customer model right so what we're gonna do now is convert this data into a customer model all right so i'm going to close the simulator quickly because it does make the fan on my computer go crazy and let's just jump back into the code here i'm going to get rid of this print statement because now we understand what it is we don't need to see that anymore and before we use any kind of codable i'm going to manually decode this data so basically we're going to do is the opposite of this get data we had this dictionary we could we use the json serialization to convert it into json data and now that we have json data we first want to convert out of json data and then get this dictionary so what we're going to do is say let local data equals try and we'll use a json serialization dot json object because we know it's a json object we're going to use the one with the data completion the data of course will be our data and then we're not going to use options so we'll just open and close the brackets here all right from this local data we want to try to cast it as a dictionary that has keys of strings and values of any so let's say let dictionary equals local data as the question mark because we're going to try to convert it into a dictionary of string colon any all right and if we hold the object button and click on local data we can see that it is optional and if we click on the uh the dictionary we can see that it is also optional so i want to make sure we have both so we are going to say if let this comma and this then we'll open the brackets so if we do get the data if we do get the dictionary then we go into this closure here and we're basically going to try to extract the id the name and the points from this dictionary so i'll say let id equals dictionary and we're going to access the the key by using a square brackets and we'll put in the id this key needs to be exactly the same as this key we're going to try to cast it as a string we'll say let name equals dictionary name as string let points eagles dictionary points as int and let is premium equals dictionary is premium as bull and once we have all of those we can then create a let new customer equals customer model and we can pass in our id our name our points and his premium we need a quick error because we are optionally casting these there's a chance that this doesn't work and this id is actually nil and that causes a problem when we create these so i want to point out here that if you're following courses that are telling you to explicitly unwrap these it will get rid of the error messages but that is not good coding because this is not safe and if for some reason this doesn't work this will crash your app and we do not like this so i never really recommend using this explicit unwrapping we could give these default values so we could say if this is so we could say if this doesn't actually work we will just do two question marks and we will default it to maybe a blank string or just a blank id or whatever you want here as a default value but even further i'm just going to put all of these into the if let's statement so we're going to make sure that we do get all of these before creating a customer so i'm going to press enter on this and i'm going to cut these paste them inside the statement just tab them over and let's just add commas at the end of them and then i'll put this bracket back up here so we're going to say so we're saying if we get all this data we can then create a new customer and finally we can set the customer equal to new customers remember this customer is the published variable that should show up on our screen all right i'm going to run the simulator one more time and as soon as it loads we now do see our data on the screen so just to reiterate what we did because i know it might have been confusing we created fake json data because when we actually download from the internet it's going to come as data so what we did was create a fake dictionary here we converted into json and this data variable here which is when we called get json data is how it's going to come from the internet and now we need to take that data and convert it into something that is usable so here we manually decoded it we took that data stripped out the json into some kind of local data we casted it as a dictionary that we can then use and then we looked into that dictionary for an id a name point in his premium and if we got all that information we created a new customer and then we put it onto the screen all right i hope you guys are still with me so far but now we're gonna get into the cool stuff this was a lot of setup so while this works the problem here is that if there were a bunch of places in our application where we wanted to take data and convert it into customer models we wouldn't want to have to write this code a bunch of times and even writing it just this one time is kind of tedious i know we only had four variables sometimes you'll have data models with a lot of variables way more than four and in those cases you don't want to have to be worrying about all of this trying to cast it as strings and such so in swift we can use something called deep codable protocol and that's what we're going to get into right now so let's first go back up to our customer model and let's review what initializers are because when we call when we create a customer model down here it created this initializer for us and it basically has the id the name the points the is premium so what that initializer really is is a init it has id of type string it has name of type string and type this out if you're following me don't just listen because we're going to use this in a second points of type int and is premium of type bool and we'll open the brackets and then sets self.id equal to id self.name equal to name self.points equal to points and self.is premium equal to is premium so this is your default initializer that you're already using down here it's just that swift had made this for us and here we are initializing with all of these parameters but what we can do is actually make customer model conform to decodable and this basically allows us to initialize a customer model from some sort of data and it will decode from the data into a customer model so to conform to decodable we need a new initializer that has the from decoder in it and you'll see here in this initializer we can't pass in all of our data manually instead we pass in a decoder and to get the values from this decoder we need to do a little bit of setup we will say let container equals try and let's get the decoder dot container and we see that it is keyed by and there are a bunch of keys that we need to look for in this decoder so this container is basically just the container inside the decoder that holds all of the data and these keys that we're looking for are is going to be all of these keys that we set up down here so we manually added this id this name this points is premium but when we're using this decode by container we need to give it all the keys that it should be looking for so we haven't set up these keys yet and we get and we can do that very simply so in this customer model i'm going to create a enum i'll call it coding keys i'll make this conform to string because down here these are all strings right we need the string version of it and we will make it conform to coding key which is what we need here so we'll say coding key open the brackets and then we just need to give it all the keys that we're looking for so we'll say case id case name case points case is premium and this again it needs to be exactly what our data is coming in as so where we have our data we have is premium points lowercased and when we were decoding it we had the exact same strings points is premium and that needs to be the exact same here and if for some reason you wanted to change the name of this variable verse verse how it was actually coming in so for example this is premium maybe it was coming in with an underscore in it so we could set the raw value the string version equal to is underscore premium or however it's coming in from the data we don't actually need to do this because our strings are perfect as is but if you needed to customize it this is how you would do it so now that we have our coding keys we can pass them in here we can say coding keys dot self it's just referencing this enum that we just made and after we get this container we then need to get all of these values so we'll say self.id just like we did here from this initializer we have to set up all of these values self.id equals try container dot decode and you'll see that all of these decodes all these decodes have types so this id is actually a string and i'm going to look for the one with a string dot type we're going to pass in string dot self here because we want it to be a string and then we just need to add in what key this id should be for and of course it will press the period and it will be the id we're going to do this for all the variables with self.name equals try container.decode looking for a string again this will be string dot self dot name self.points equals try container.decode i'm going to use the points and this will be int dot self this will be for the points and then finally self dot is premium equals try container dot and this one is a bull so look for the bull it's up here bull dot self and we'll use dot is premium so now we've completed our initializer that will decode for us and because we have this decoder and it conforms to decodable when we scroll back down in our app we actually don't need to manually decode this at all so i'm going to highlight this and press the command backslash to comment this all out because we're not using it and we're going to take our data and we're going to say self.customer equals we'll add json decoder so we're using the decoder now open close parentheses we're going to initialize a new one and then we will do a decode from and now we need to give it a decodable type something that conforms to decodable protocol and of course our customer model already conforms to decodable so we can add in customer model dot self and we want to decode from data which is our data all right and then we're going to get this error that the calls marked with try so we could use this optional try here but let's just be a little more explicit so let's use an actual try we're gonna have to use a do catch statement so we'll say do we'll put our code inside here the middle cache will say let error open the brackets and then here we will print out error decoding backslash open close parenthesis and we'll print out the error i don't think we're going to actually have to catch any errors because we did everything correctly but let's re-run our app quickly i'm going to build it to the simulator and when this app loads we still see our data on the screen so this time we didn't have to decode all this manually and instead we just have this one line of code that takes the data and it decodes it directly into a customer model so as you can see how this is much more efficient than how we started and because we're not getting these errors i could even make this i can make this even a quicker one-liner by just putting it outside the do statement and making the try optional so it is fallible and i can then just comment this out as well and we literally have one line to get from json data to a customer and this is efficient coding again i'll run it make sure it still works all right and while we're here now we've learned the decodable protocol i also want to introduce you to the encodable protocol it's definitely used less because a lot of times for example we're downloading json from the internet it's much rarer to have to actually post json data to the internet and send it to the internet but that is possible and sometimes we want to convert our customer model back into json data so down here we we manually created a dictionary and then converted it to json but wouldn't it be nice if we could just create a customer model like we did here and then convert that directly into json well yeah it would be nice but we can't right now because the customer model only conforms to decodable and not encodable and all we have to do is add the encodable protocol and to conform to encodable all we need to do is add a function down into our model we'll type out in code and we have this function for us that it's an in code two and basically it's the opposite of the decoder so first here we'll we'll create a variable we'll call this container and we'll set this equal to the encoder dot container keyed by coding keys and dot self so here the container had values and we had to strip out values here we're creating a blank container and then we need to add the values so now we'll say try container dot in code and again we have types so first we're going to do the id which is string we're going to we're going to pass in the actual value which is the id and this is the actual current value of the id that's in our customer model so to this variable up here and the key for the id of course will be dot id we're going to try encode string we're going to do the name for name try container dot in code we want the integer and this will be points four dot points and then try container dot in code looking for the bool and it will be is premium for dot is premium and again this points this is premium we're referencing the current points in his premium in the model so now we have our function to actually encode our model into data so going back down where we have this dictionary instead of this dictionary let's just create a new customer here we'll say let customer equals customer model let's initialize a new one and you see when we have this initializer now we have two options we have our default we also have and we also have the ability to to initialize with a decoder but of course we're doing this manually let's just do our regular initializer let's change up the id here let's do just maybe one one one the name will be emily points let's do 100 and is premium false so before we took this dictionary and converted into json data but we don't actually need to do that anymore so i'm going to highlight it comment it out and now we can just convert this customer in to json data so we'll say let json data equals json encoder open close parenthesis dot encode and here we can pass in the customer and just like we had down here with that optional try we can do try question mark and again you can see how this is more efficient than this because we don't have to actually worry about creating these dictionaries anymore we can just take our model as is in our app and we can encode it with a single line of code and it goes into json data so if i run the app one more time we should now see this customer here it is and remember our customer we're encoding it into json data and then here we are decoding it from json data and i just love how simple this gets because all this extra logic could get very very clunky very very long to write and using these protocols is super efficient because customer model one line to encode data one line to decode that's just awesome to me and finally after all of this talking all this setup you're probably wondering why this video is called codable because we haven't even looked at the codeable protocol yet well this is the magic of the codeable protocol because i can go up to our model here and codable basically includes decodable plus encodable so let's just write that real quick codable equals decodable plus encodable and instead of conforming to both of these we could just conform to codable and if i run the app again now we're just conforming to codable it should still work we should still see the data but the really really cool thing about codable is that it does all this logic here for us so when we use decodable encodable we had to explicitly decode we had to explicitly encode and if you need to do that in your app you still can but the magic of the codeable protocol is that this is all done behind the scenes for us and we don't even need to worry about it as developers so i'm going to highlight the coding keys the initial init the decoder init the encode init and comment it out so in our customer model all we have is where we started with these four points and then we conformed to codable so we didn't write any decoding logic at all we didn't write any encoding logic and if i run the simulator again it still works so all we have is this little bit of code we have one line to decode we have one line to encode so all this extra stuff we did just because i wanted to build you guys up to really prove what codable is doing behind the scenes because i could have made a whole video where we just conformed to codable we ran the app and it worked but you wouldn't really understand what was going on so that's why i wanted to build up to this and as you can see now codable is super super powerful because it decodes it encodes for us and it saves us so much time and stress and worry trying to decode manually now there will still be times in your app when you might have to decode manually because maybe you have to customize the coding keys for example and if you do of course now you know how to add a decoder as well all right guys we're gonna start using the codeable protocol as we start to download data from the internet in the next couple videos so i hope you enjoyed this video i hope you learned something as always i'm nick this is swiffle thinking and i'll see you in the next video [Music]
Info
Channel: Swiftful Thinking
Views: 1,927
Rating: undefined out of 5
Keywords: SwiftUI Codable, Swift Codable, Swift how to use codable, Swift what is codable, codable, Codable swift, Decodable, Encodable, What is Decodable swift, what is encodable swift, SwiftUI decode JSON, SwiftUI download JSON, SwiftUI codable with JSON, SwiftUI JSON data, SwiftUI how to use codable, what is codable SwiftUI, what is encodable SwiftUI, what is decodable SwiftUI, how to decode JSON swift, how to decode JSON SwiftUI, SwiftUI Codable protocol, Codable protocol
Id: H9mt8WjpZgM
Channel Id: undefined
Length: 35min 22sec (2122 seconds)
Published: Wed Apr 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.