iOS and Swift JSON Encoding and Decoding

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
project for encoding and decoding last week we talked about encoding and decoding pls pls or what's native to iOS and Swift okay they're just property list but the reality is is we need to deal with JSON data so any of our web-based data is gonna be JSON data if we're dealing with restful api s or anything like that it's gonna be json data so this is kind of a build up to actually dealing with those web api s-- so we know that when we make requests for data to get data it's gonna come back as restful data it's gonna come back its json data more than likely okay so what I want to do is I want to create an application where we're encoding and decoding JSON okay and then we'll complicate things from there okay so I'm gonna I'm just gonna call this JSON encoding it's not just JSON encoding it's JSON encoding and decoding so maybe a better name and due to the fact that we're not using a web based API what I want to do is I want to have two separate data types so I want to have one data type that we let's just say that we're dealing with students and then I want to from those students I want to bring back people okay and that might not be a one-to-one mapping with properties right like students will have additional attributes that people wouldn't people have additional attributes that students well I guess all students will have all the people data but it's not necessarily a one-for-one mapping like when last week when we were dealing with p lists it's like here's the data let's decode it and encode it and it's just a one-for-one mapping so to kind of hack through this example because we don't have two different data sets what I want to do is I want to have two different classes okay well encode one and decode it into another okay so we're gonna go from one type to another it's kind of the plan so before we do that though let's just work on encoding JSON just like we did with a P list I have an object I encode it and decode it like I need to be able to save it to disk and then recover it from disk so that's kind of the simple solution for the time being so let's do that first I'm going to start with a class definition so let's just start with a student so our student class we want to make it codable right so we can encode it and decode it so our class is going to be codable and then we need some attributes like so we care about their first name and last name and student ID and email number of credits so some int required credits progress okay and it's not gonna allow me to deal with this as a double so it's gonna do integer division I don't want integer division I want okay this is my student class I need an init method for my student class because I don't have any values so I need my init method so I'll take the first string last is the string ID is a string email there's a string credits as an int required credits isn't it okay so I would just want to map those incoming parameters to the instance variables okay so there's my initializer so I can create instances of student objects and it doesn't I don't have to set that progress oh thank you just ID there we go okay so there's my student class what I want to do is I want to create a couple of students and then I want to encode those and save them to disk okay so if I go to my view controller I'm going to have a method called encode students no parameters no return type I'm just gonna do some stuff I'm gonna have encode students I'm gonna have decode students and then in order to do that I'm gonna need a place to store them so I'm gonna have a function that will get me my URL that will return a URL so really what we're talking about is encode to JSON right to disk here we're talking about read from disk and decode from JSON that's ultimately what I wanna do okay so then in order to do this I want to get the users documents URL again so we did that last week so Doc's URL is gonna be equal to our file manager that default got its files right no URLs and then I'm gonna have a search directory I want the documents directory I have to search for the document directory and then I just want the the user mask so I'm only looking in this specific mask it brings back a collection of URLs I don't want a collection of URLs I just want the first one that's going to man okay so that's my documents URL I need to have a file name attached to it so this is just a directory path like that Docs URL is just a directory path if we're talking about like a normal file system so what I'm gonna do is I'm going to say let's return the docs URL I want to append a path component which is gonna be the file name so in our case we're talking about students and then I'm going to be appending a path extension the path extension of the JSON so my file names gonna be students dot JSON and it's gonna be in that users documents directory that's what that urls indicating okay okay so when we encode students I need a JSON encoder so here's my encoder and coder is going to be a JSON encoder and then what I want to do is I want to take that encoder and encode some encode abaut item my students I don't have any students yet all right so let's create some students then we'll come back to this encode method okay so this class will have some students I'm gonna make it an array of student equal to and then here's a student object first bill last ate ID one email eats at msn.com let's say he has 84 credits of 120 that are required so there's one student and then I just want to create a couple of students so Steve Jobs s jobs matcom I think he graduated I don't know that for sure why is this complaining oh the ID I think he graduated one last student so Amazon he didn't get very far okay so I have a collection of student objects that's based on my class definition as all the information about my students and then we build that collection of students we want to deal with that collection of students so what I'm going to do is I'm going to encode that students collection I don't know why I ended up in student okay this is a throwable method meaning I have to try to do this and what's gonna happen is when I encode this it's saying take this collection of student objects so that a collection of Swift student objects when I encode them what I really mean is I want to take that collection of Swift student objects convert them over to like a string of JSON data so I want to try to do this it's a throwable method meaning I could have an exception I want to try to see if that's actually gonna work and what I'm gonna do is I'm gonna say if I can create some variable called encoded students so if I can do that then life's good encoded students is a data object so what I want to do is just print that JSON data just so you can see what the JSON data looks like before we write it to disk like eventually I should be able to just take encoded students and then there's a write method eventually I should be able to do that but what I want to do is I want to print those encoded students so I can't just print data because it's just gonna come back as a bunch of binary data that I can't see so what I want to do is I want to string where I set the data equal to this encoded students and I want to say the encoding is equal to utf-8 encoding so I'm basically taking that data and converting it to a readable utf-8 string it's fine there so what I want to do is just take a look does that actually look good and what we should see is we should see the output of that encoded student's collection should be a JSON collection square brackets curly braces key value pairs and that's the idea so when I run this eventually we get our collection of objects so here's the first object for the first student that's highlighted and what's happening is it's escaping all the double quotes because it's a string and it's saying hey there's double quotes inside of the string which is from the JSON data indicating those are the keys or the string values this is the data this is what I want to write to the file system this is what I could expect from a web service like this is the response that I might get from a web service saying hey give me the students at MATC that are enrolled in this class I think if I had an iPhone application saying you know here's my class roster this is the data that I'd expect back something like this okay so we're able to print the data let's go ahead and write that data to disk then so I have encoded students so I take the encoded students the data object I want to write it to my specific URL so I know the URL it's this return value from this get URL method so let's just use that method and then the options are no file protection I want to be able to overwrite the file yes the data changes and it says hey that can throw an exception but it's not marked so I want to try that so we're writing them to disk okay great it seems like a reasonable thing to do what I want to do is I want to cheat a little bit here I'm gonna go over to my student list and I'm going to implement the custom string convertible protocol and I needed a description then and what I'm gonna do is they're gonna return just the first and last name of the student so I'm gonna say you know here's the first name and the last name okay that's my implementation for that custom string convertible and the reason I want to do that is if I go to my storyboard alright sorry not my storyboard in my view controller I want to I'm gonna take out this print statement where I'm printing the JSON data I'm going to print my students okay so we should just see that array of data and it's gonna call that custom string convertibles description method so we'll see my four students first and last names when I run this okay there's my array with my four students what I want to do is after I've encoded the students meaning up encoded them and stored them to disk I've saved them essentially I probably want my comments reflecting the code it'd be good after I've done that I'm going to clear all of these students students remove all empty and we should be able to see that so if I print students and the way I'm gonna handle this is I'm gonna say after removing all okay so now I should see an empty array okay so really I'm just proving to you that they array is empty right so we started we had students were able to print out those students we saved them to disk so they're on the file system that JSON data is on the file system we clear it out and what I want to show you is that okay we've cleared it out we can reload that data from disk now by decoding those students like that's what I want to do is I want to decode the student objects so that we can see them again okay so I want to let my decoder it's gonna be equal to a JSON decoder okay and then I want to initialize some data and I'm going to initialize it and if I look there's an Annette from the contents of a URL stated at Anne it from the contents of a URL and I wonder if it's failing because I have to actually try catch that okay so I'm trying to initialize some data from a file off the filesystem so what I want to do is I want to get that data object so I'm just going to say if that data equals all that stuff so if I can get the data off the filesystem then I can do something then I should be able to if let decoded students equal to try again it's gonna throw an exception if I don't I should be able to use my decoder to decode I'm gonna decode data but in order to do that I'm gonna get an array of student objects loose from data so if I actually get a collection of decoded students then I should be able to assign that to that collection of students and if I've done that correctly then I should be able to then print out all my students again after decoding so now we should see all three steps right we start with our initial grouping of students we write them to disk we clear the collection and then I'm never decoding the students so I don't see that third set so I start with all of them I read it to disk I remove them all and then I never reload them because I never actually called the method to reload them life's good it's almost too easy when it works right how does that happen not that much different than last week right like we used a plist encoder and decoder but essentially the exact same thing that we did last week so nothing is changing all that much when we work with JSON versus P ulis okay so just a different encoder type here's where things are gonna get different though okay so this is just kind of a review from last week we're all on the same page we're able to get URLs were able to write to our filesystem we're able to get data from the filesystem and write to the file system so that that's good where we run into problems though is let's say encode a collection of students I consider that my API that's the data that I have on the filesystem so that's the data that I have available to me and what I want to bring back is people and people don't necessarily have the same attributes like they're not gonna have a student ID they're not gonna have credits required credits progress like they're just not gonna have that information it's not necessary okay so what I want to do is I want to encode a collection of students and then I have data for students it's gonna be on the file system what I want to do is I want to pull back a collection of people when I decode this so I'm going to add another class called person I'm just gonna copy and paste the student class and then we can kind of work from there okay this give me my person class still want a first name still want a last name don't want a student ID don't want credits don't want required credits don't want progress okay same thing with this initializer no longer need credits or required credits how did I ever do that without a student ID well I have it I just didn't see it there we go so we just have first name last name email okay so great I don't need the student ID I don't need credits I don't need required credits I don't need the calculated field so my person is kind of a dumbed-down student okay that makes sense yeah yeah yeah what I want to do is I don't want to get rid of the code to decode students what I'm going to do is I'm going to have another function decode students to people okay I'm going to funk decode students to people okay so a lot of this stuff is gonna be the same thing right like it's a lot of the same stuff and I guess I should probably fix that comments okay except I don't want to decode into students I want to decode into person objects and I'm gonna call this my decoded people and I don't want to store a local variable I don't want an instance variable I just have my decoded people so after decoding I'm just gonna print out my decoded people okay so I just added another method I didn't get rid of the encode and decode students but now I want to add one more method where I'm trying to do a type conversion so on disk I have students and I want to bring them back as people or maybe I have a service that's getting all the students and I'm mapping my students because now I want to say these are graduates and I have new information about the graduates like I want to know where they're working and how much they're getting paid and what field and stuff like that so we can collect data on those graduates all right they're no longer students they're graduates different data type don't have the same fields don't care about how many credits you had anymore don't care about your GPA you graduated we're treating everyone the same okay so same type of conversion here we're converting students over to people okay so I want to try that all right so I want to decode students to people this fails if I don't have an exact mapping [Music] so when I say it fails if I don't have an exact mapping it worked right everyone okay with that so I want to show you what it looks like like I want to just make sure my labeling is correct after decoding into people you see it works fine that's this one right here and the reason it worked just fine is because the the attributes were named exactly the same right when I when I went from students over to person I left the attributes exactly the same I just removed some okay but as long as they have a one for one mapping from here's the key value pairs that are in that JSON file as long as that class name as long as that all matches up life's good so what I want to do is I want to change things so I don't have a one for one mapping okay so I'm gonna go to my person and they're no longer gonna have a first name they're just gonna have first last and then email address I'm changing everything like I don't need to but it doesn't hurt anything so first last first last and then email address okay so the class definitions okay but it's now different I don't have the same attributes that I in my person class I don't have the same attributes that I did in my student class okay and additionally what happens if I add another attribute okay so my person is going to have a home address this would have broke things as well okay so now I try to run this you'll notice I never get after decoding to people why not okay so I have a try block that just bonks out of it is that okay yeah I mean yeah my program didn't crash but is that really what I want like I'm trying to build the application I'd like to know that that didn't work right be nice to know so how do i how do I determine that so I'm gonna argue that it failed right here on this decode I got that's where it failed okay I'm telling you that just because it's an easy thing what I want to do is I want to do this so I want to do this stuff and I no longer want to optionally try this I want to try it and if I run into a problem I'm gonna catch it I don't like that indentation but use of local variable get before it's declaration I must have a mismatched yeah I do I'm gonna let that variable equal to the Tri yeah I'm like why is it indenting this for me it looked off to me so now I do this stuff it's kind of like my try-catch blocks I do these things and then catch any exceptions okay so all I'm gonna do is print the air this air object is automatically given to you in your catch block and now I'll see the air you can yeah this is just generic he not found first yeah it's a pretty reasonable error right okay so now I'm getting errors right I might say hey the error occurred in this method so when I catch the air I might want to give detail about where I found the air there's additional information about the air but I just find that useful I like I owed around it so often that sometimes when you're just trying to get things to work it's like no I like I need to know what the air is like why is this not working over the weekend I was working on the the book demo of like consuming data from an API and their data is like from the Astronomy image of the day so I just kind of go in through the book example of calling that API and it wouldn't work I'm like why the heck is this not working and then turns out like with the image from the weekend was a video not an image and I was trying to put it into a UI image and then later in the book it talks about oh yeah sometimes it's a video okay oh my god and they're like it's beyond the scope of the book to handle video so don't worry about it and so then I'm like oh yeah like that makes sense and then I was able to change it to a specific date to get an image and that it worked fine but yeah it's like I don't know what the air is because I keep working around it and it would just crash when I try to do something and I just avoid the air it wasn't crashing my application it just wasn't working like we're having here well now it's crashing and when I say crashing crashing gracefully right like the applications still running I can caught the air I figured out what the air is the application is still running likes good so sometimes I prefer this okay so we don't have that key right our data has a first name but we're trying to map it to first and our data has a last name and we're trying to map it to last and our data has an email and we're trying to map it to email address we screwed up all the mappings right so in order to handle this we need to go back to our person class and when we want to change those mappings we have to implement a specific coding keys protocol which is an enumerated type that basically says here's the keys that are coming in how do they map to this object so I need an enum called coding keys that takes a string and maps it to a coding key okay and basically it's gonna say you know I'm taking the first name and I'm mapping it to first and I'm taking the last name and mapping it to last and I'm taking the email and mapping it to the email address that's my mappings that I want to set up and that can be anything right like your service says the key value pairs are XYZ you want a map into ABC okay this is how you do it like this this attribute maps to my classes attribute on the right hand side so the right hand side is this class's attributes okay in addition to this one additional thing that I have to do so you'll see it doesn't conform to the protocol decodable I got that error now because I implemented this enum for coding geese I have to describe how to initialize a new instance of a person from a decoder so I have this init method saying hey if you pass it on all this information this is how it initialize a new person I have another init method so I'm going to overload the init method saying hey if I'm initializing a person from a decoder this is how I should initialize that person I'm gonna have another init method and this will throw an exception if it doesn't work so I have to have that throws and I think I might even have to have the fact that this is a required initializer okay in order to do this I need a value container this is where that coding keys and yum comes in and then the value container what it'll do is I can get all of those different values so I can say I want to grab the first name and the way I'm going to do that is I'm going to try sorry I'm gonna go to my value container and I'm gonna decode decoding a string for a specific key so the coding keys at first and I'm gonna keep doing that so self dot last I'm gonna try to go to my value container I'm gonna try to decode again it's a string because it's the last name and then I'm gonna do the same thing for the email what's the reason yeah so what it is is just a data type so instead of saying I want an instance of a string I'm talking about the string data type that's what I'm decoding this into so if this was like let's say I wanted to decode this into a pet like it might be something like pet that self alright so that we're really talking about the data type as opposed to an instance of that data type so we're just talking about strings here because that's what the data types are they're just simple data types yeah yeah so what it's basically saying is for that property I'm trying to decode this into a string yeah yeah why does this not conform to any codable I think it should I don't think I have to know I don't oh yeah you do have to make it optional because I can't create it without a home address when in case key does not match I should be okay now I think I think it should oh I'm mapping my stored attributes I have these exactly reversed so I want first map to the data that's gonna come across his first name I want last mapped to the data that's gonna come across his last name and email address to come across as the data that's mapped to email okay now this is screwed up so this is first last and email address now you can say I wasn't optimistic but looks like it runs I can almost promise you're gonna implement all of this stuff and like I was saying we're kind of building up to those web-based API so our API is gonna return data unless I've written every single bit of code I probably don't have a class that matches one for one to say oh this is what the API is returning this is what my class needs they're probably just not gonna do that I don't need everything from the API I probably need bits and pieces from the API I think I'm getting a collection of students and I want to map those two graduates or people in our case I don't need everything I don't care how many credits you took maybe I just need different data looking at the network traffic yep so we can start to look at network monitoring too when we start to get to the web stuff so you can see here's the data that's actually getting sent to you and like why is it not getting mapped correctly so you could do it with air logging but you can also do it with network monitoring and there's network monitoring tools that are built into Swift so like as I make that request I want to see like hey did my request look the way it should for that API request and then is the API response this what I'm expecting it to be sometimes it changes and you don't know or like sometimes things are optional and you don't realize that they're optional and then they don't exist and it's like oh so right now if I'm looking at this code like I'm trying to do this but I don't assign a value if it fails so if that data was optional in some case like I might want to do some kind of conditional operator to say hey that it's an empty string if it's not alright so I'm going to look for a conditional I can't tell you how many times I do this but it's it's the same you know it's like hey I'm getting this data set back and now I need to map it to one of my objects and it's not a one-for-one mapping so like it's constant I don't store data on my device so in this class it's kind of nice like hey we can write data to disk and for small applications I think that's probably reasonable but I just never do it because it's like you in almost instantly grow out of it if your applications gonna get used so it's way nicer just to have a web server sitting on AWS to say hey store my data there in RDS right and then my data is in Amazon and now if I want to build a web application on top of it my mobile device is gonna be sunk up with my web application and all my data is in one spot not on my device and now I don't have to worry about like oh I did some work on my device I have to sync up my device with the web application so that the web application knows about the changes I made on my phone that just doesn't make any sense querying that is sometimes tough though [Laughter] so like you're probably too too young into this career to remember a time when not all your phones were connected devices and you didn't have an internet connection and you didn't have a cellular connection so a lot of times what would happen is we would save data on locally on that device and then at some point you would have to sync up that data that syncing process sucked so bad because you'd run into merge conflicts like hey one user updated this record and another user updated this record and like how do I deal with that conflict and as a programmer I have no idea and like if you've ever used git and had merge conflicts like that's essentially what used to happen to you as a developer and you had to like resolve those merge conflicts and I had no idea how to resolve them and people would get pissed off about that right hey last one wins is easy to implement hey not my problem but it's it's completely your problem because you look like the idiot programmer that didn't know how to write this like oh this person edited it and then I made changes to like a stored copy of it and now my changes aren't reflective of that person's changes like it doesn't work okay so that's all I wanted to really get through today is encoding and decoding data and those custom table view cells next week we're gonna get it into closures the lab is a little bit longer so I I'm kind of giving you a warning although if you've dealt with closures before so Map Reduce filter it's similar like Swift doesn't necessarily change that process and I guess here you can take it one of two ways like okay I have to do a bunch of work and I don't know how to do this and it's gonna take me a long time if you haven't seen Map Reduce filter now I think it's pretty close to like JavaScript and Swift are pretty similar and I guess the upside to this is I learn it in Swift I also learn it in JavaScript or I know it in JavaScript I also learn it in Swift so it's not like hey I learn it in one spot and then it doesn't apply anywhere else the syntax is a little bit different and Swift so like when you say it's a little backwards like the syntax is different so it's not the same as JavaScript Swift Oh argue JavaScript backwards well it used to be Microsoft in the rest of the world so yeah I mean who's right who's wrong yeah there's always got to be a villain right yeah so I'm gonna stop here for today next week we'll get into closures and then the week after that we'll get into those web-based api's which will implement those call Bax which will require closures okay so well kind of deal with the syntax so it's gonna deal with the encoding/decoding closures it's kind of all gonna come together with those API requests okay so I'll stop here for today you do have a lab that's due and like I said if you're comfortable with it I think it's a pretty easy lab but if you're not comfortable with it like staying get help okay cuz it doesn't have to be that hard you don't have to go do it on your own like I can help you so like the lab shouldn't be hard but I guess you can make it hard if you want to so I'm gonna I'm gonna up
Info
Channel: Bryan Witkowski
Views: 193
Rating: undefined out of 5
Keywords:
Id: uR_4CrE7zJs
Channel Id: undefined
Length: 49min 3sec (2943 seconds)
Published: Tue Nov 20 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.