0 1 00:00:00,480 --> 00:00:05,160 In this lesson, we're going to be learning how to parse the response that we're getting back from 1 2 00:00:05,160 --> 00:00:07,530 OpenWeather Map's servers. 2 3 00:00:07,680 --> 00:00:15,090 So now that you've seen how closures work, let's convert our completion handler here to an actual Swift 3 4 00:00:15,090 --> 00:00:16,740 closure. 4 5 00:00:16,740 --> 00:00:24,120 Instead of creating session.dataTask with URL and passing in the completionHandler as a 5 6 00:00:24,180 --> 00:00:30,930 actual method, I'm going to go ahead and initialize this dataTask again, because I'm going to borrow 6 7 00:00:31,020 --> 00:00:33,660 Xcode's code completion to help me. 7 8 00:00:33,750 --> 00:00:39,270 So I'm going to choose the one where I give it a URL and I end up with a completionHandler that 8 9 00:00:39,270 --> 00:00:39,820 triggers 9 10 00:00:39,840 --> 00:00:46,230 once it's done with the task. And the URL is, again, going to be just the URL that we got from 10 11 00:00:46,440 --> 00:00:47,930 our optional binding. 11 12 00:00:48,090 --> 00:00:56,100 But here in the completionHandler, where you see this gray area, which is the code placeholder that 12 13 00:00:56,430 --> 00:00:58,910 is telling us what it's expecting. 13 14 00:00:59,130 --> 00:01:03,690 If you go ahead and select it, so turn it blue, and then hit enter, 14 15 00:01:03,690 --> 00:01:08,430 it should format it into a trailing closure automatically for you. 15 16 00:01:09,180 --> 00:01:16,230 So now that we see this familiar closure format, we can go ahead and add in the names of the inputs. 16 17 00:01:16,290 --> 00:01:19,780 So that's going to be called data, that's going to be called response, 17 18 00:01:19,860 --> 00:01:22,410 and that's going to be called error. 18 19 00:01:22,410 --> 00:01:30,170 And now inside this code block, we're going to move in everything that used to live in our handle method, 19 20 00:01:30,540 --> 00:01:37,470 and it's now going to go inside our closure. And we can delete the separate method. And then I'm going 20 21 00:01:37,470 --> 00:01:45,780 to select everything and hit control I, or whatever your shortcut might be if you go to Editor, Structure 21 22 00:01:45,840 --> 00:01:47,110 and Re-indent. 22 23 00:01:47,110 --> 00:01:48,450 So this is what I see. 23 24 00:01:48,450 --> 00:01:50,020 You might have something different. 24 25 00:01:50,250 --> 00:01:57,440 And now I've reformatted my code to look a lot more Swifty with my anonymous function here. 25 26 00:01:57,690 --> 00:02:05,850 And I've got my trailing closure which is going to carry out this task once it completes with the 26 27 00:02:05,850 --> 00:02:07,430 dataTask. 27 28 00:02:07,900 --> 00:02:14,470 So now that we're done with getting hold of the data, we don't really want it as a dataString because 28 29 00:02:14,860 --> 00:02:20,830 this is impossible to read even if I concentrate and really squint my eyes. 29 30 00:02:20,830 --> 00:02:30,160 Instead, we're going to pass this piece of data and turn it into an actual Swift object with properties 30 31 00:02:30,190 --> 00:02:32,170 and methods. 31 32 00:02:32,170 --> 00:02:41,320 So to pass this data which is currently in a JSON format and I know it's a JSON response because when 32 33 00:02:41,320 --> 00:02:47,890 I look at the documentation, you can see that the example of an API response in the JSON format looks 33 34 00:02:47,890 --> 00:02:49,990 exactly like what we've got. 34 35 00:02:49,990 --> 00:02:57,430 And JSON formatted data that's being transported across the internet, is probably one of the most popular 35 36 00:02:57,520 --> 00:03:05,860 and one of the most widely used formats. And other formats like XML is fast going out of fashion. 36 37 00:03:05,980 --> 00:03:08,920 But what exactly is a JSON? 37 38 00:03:08,920 --> 00:03:11,110 What does it actually stand for? 38 39 00:03:11,110 --> 00:03:15,940 Well, a JSON stands for JavaScript Object Notation. 39 40 00:03:15,940 --> 00:03:21,670 This actually comes from the JavaScript world, the web world, where there's a lot of data being transported 40 41 00:03:22,000 --> 00:03:29,610 across the internet, and they need to make it as efficient, as lightweight, and as small as possible. 41 42 00:03:29,710 --> 00:03:37,490 I want you to imagine that you start out with a wardrobe and this wardrobe happens to be an object that's 42 43 00:03:37,510 --> 00:03:39,520 created in JavaScript. 43 44 00:03:39,520 --> 00:03:46,370 So this is where a JavaScript object would look like. And that created kind of almost like our dictionaries. 44 45 00:03:46,420 --> 00:03:48,910 But in this case, the object is called wardrobe. 45 46 00:03:48,910 --> 00:03:54,310 It has a property called doors which is set to equal to a property called drawers and a property called 46 47 00:03:54,310 --> 00:04:00,890 color. When this is being transported across the internet in order to save space, 47 48 00:04:00,910 --> 00:04:06,510 we're going to get rid of all this formatting which doesn't really matter while it's in transit anyways. 48 49 00:04:07,210 --> 00:04:16,140 And we're going to turn it into a flat pack wardrobe like the ones you get from IKEA. The flat pack wardrobe 49 50 00:04:16,150 --> 00:04:23,590 still retains all of the most important parts of the data, namely the syntax, the properties separated 50 51 00:04:23,590 --> 00:04:33,490 by commas, and each object encased in a set of curly braces. But it gets turned into a string, rather than 51 52 00:04:33,550 --> 00:04:40,990 an actual object. But once it arrives on the other side, once you've gotten it delivered from IKEA and 52 53 00:04:40,990 --> 00:04:46,720 you've managed to find all the screws which are impossible to find, and you've built your wardrobe back 53 54 00:04:46,720 --> 00:04:55,030 up again, then you still have a living, breathing, large wardrobe. But during transit, it was turned into 54 55 00:04:55,090 --> 00:04:59,360 a much smaller format so that it can be transported easily. 55 56 00:04:59,500 --> 00:05:06,030 Now, in our case, we don't actually want to unpack the JSON into a JavaScript object. 56 57 00:05:06,190 --> 00:05:10,790 What we want is a Swift object to come out of it. 57 58 00:05:10,870 --> 00:05:17,890 So we would initialize our Swift object with either a struct or a class constructor with properties 58 59 00:05:17,980 --> 00:05:20,290 like doors, drawers, and colour. 59 60 00:05:20,320 --> 00:05:23,040 So let's see how we can do this. 60 61 00:05:23,410 --> 00:05:29,890 So I'm gonna go ahead and delete my comments, just so that it's easier for you to see what's going on. 61 62 00:05:29,890 --> 00:05:35,380 Feel free to keep your comments or any additional things that you have in your code if you wish. 62 63 00:05:35,380 --> 00:05:39,740 But I just want to tidy up the code a little bit so you can see more at a glance. 63 64 00:05:39,820 --> 00:05:46,630 So down here below performRequest, I'm going to create another method which is going to be called 64 65 00:05:47,110 --> 00:05:48,040 parseJSON. 65 66 00:05:48,160 --> 00:05:55,180 And this is going to take a single input which is going to be the weatherData and this is, of course, 66 67 00:05:55,180 --> 00:06:01,990 going to be the format of data which is the format that we get back from our dataTask. 67 68 00:06:02,380 --> 00:06:10,570 So then we should be able to call our parseJSON method here and pass over this unwrapped safeData 68 69 00:06:11,140 --> 00:06:14,830 which meets the requirements of being a data object. 69 70 00:06:15,490 --> 00:06:21,690 But notice how we're getting a error here telling us that call to method 70 71 00:06:21,770 --> 00:06:28,040 'parseJSON' inside a closure requires an explicit 'self.' 71 72 00:06:28,060 --> 00:06:35,890 Normally, when we call methods such as when we called performRequest, we didn't actually need to say 72 73 00:06:36,160 --> 00:06:45,880 who was the object that owned this method performRequest to call this method. And in fact, the full way 73 74 00:06:45,940 --> 00:06:48,570 of writing this code would have been 'self.' 74 75 00:06:48,610 --> 00:06:57,130 So call the method performRequest from this current structure which is here. Now, the reason why we didn't 75 76 00:06:57,130 --> 00:07:03,460 have to do it is because Swift is actually doing it for us under the hood, and this keeps our code nice 76 77 00:07:03,460 --> 00:07:09,580 and tidy, and we already can see that performRequest is right there inside our WeatherManager, 77 78 00:07:09,580 --> 00:07:12,380 so it is superfluous to add the 'self' 78 79 00:07:12,400 --> 00:07:13,030 in this case. 79 80 00:07:13,630 --> 00:07:21,940 But when we are inside a closure, then it can get confused about where to add the"self" and where to not 80 81 00:07:21,970 --> 00:07:28,900 add the "self," and where the method you're calling exists. Because remember our data task is triggering 81 82 00:07:28,900 --> 00:07:34,570 this method and when it gets triggered, then everything inside gets executed. 82 83 00:07:34,630 --> 00:07:43,990 So inside the closure, the rule is we must add the word "self" if we are calling a method from the current 83 84 00:07:43,990 --> 00:07:46,390 class which we are right here. 84 85 00:07:47,200 --> 00:07:49,420 So that fixes that error. 85 86 00:07:49,420 --> 00:08:00,030 And now we can focus on our parseJSON method. In order to parse our data from a JSON format, 86 87 00:08:00,150 --> 00:08:08,400 we first have to inform our compiler how the data is structured. And we can do that through the use of 87 88 00:08:08,490 --> 00:08:10,650 a structure that we create. 88 89 00:08:10,650 --> 00:08:17,640 So in the Model folder, again, I'm gonna create another file which is a Swift File, and I'm gonna call 89 90 00:08:17,640 --> 00:08:26,550 this the WeatherData because inside this file, I'm going to create the structure that's the WeatherData 90 91 00:08:26,550 --> 00:08:29,880 is going to come back in. 91 92 00:08:29,880 --> 00:08:37,870 Notice how if we have our data formatted with JSON Awesome, you can see it as a tree structure. 92 93 00:08:38,250 --> 00:08:46,140 So we're getting back an object that has 13 properties. And the first one is a property called coordinate 93 94 00:08:46,500 --> 00:08:53,580 which inside is another object that has a longitude and latitude properties. And we also have a property 94 95 00:08:53,580 --> 00:08:59,380 called a weather which inside actually has an array with a single item. 95 96 00:08:59,430 --> 00:09:05,820 So we have to basically break down this structure for the compiler to be able to chew through the data 96 97 00:09:05,850 --> 00:09:12,480 that it's getting in this format, and then we can assign property names, and we can turn it into a Swift 97 98 00:09:12,570 --> 00:09:13,650 object. 98 99 00:09:13,650 --> 00:09:19,170 So let's start with something quite simple, something that's just got a key and value pair. 99 100 00:09:19,170 --> 00:09:27,650 So for example, our name here. The property name is called name and the value is Paris. 100 101 00:09:27,740 --> 00:09:36,320 In this case, we could create our structure WeatherData and it can have a single property code name. 101 102 00:09:36,950 --> 00:09:37,900 And the name 102 103 00:09:37,910 --> 00:09:42,470 if we check is, of course, a string because it's got the quotation marks around it. 103 104 00:09:42,650 --> 00:09:43,480 So we'll sign it, 104 105 00:09:43,490 --> 00:09:45,750 the date type of a string. 105 106 00:09:45,950 --> 00:09:48,890 But this is not quite enough. 106 107 00:09:48,890 --> 00:09:58,130 In addition, we also have to say that our struct conforms to the Decodable protocol and that means 107 108 00:09:58,130 --> 00:10:06,080 that the WeatherData turned into a type that can decode itself from an external representation namely 108 109 00:10:06,350 --> 00:10:14,750 the JSON representation. Now that our WeatherData is Decodable and it's got a property called name, 109 110 00:10:14,950 --> 00:10:21,920 we can go back into our parseJSON method and create a decoder. 110 111 00:10:21,940 --> 00:10:27,530 And we're going to create that from the JSON decoder object, 111 112 00:10:27,580 --> 00:10:33,730 so this is an object that can decode JSON. And we're going to just initialize it. 112 113 00:10:33,850 --> 00:10:39,220 Next, we're going to use our decoder and we're going to decode. 113 114 00:10:39,250 --> 00:10:41,920 Now, this takes two inputs. 114 115 00:10:41,920 --> 00:10:48,700 Firstly, the data that you want to decode and a Decodable type. 115 116 00:10:48,700 --> 00:10:55,020 So a data type that we're using to decode that conforms to the decoder protocol. 116 117 00:10:55,030 --> 00:10:57,860 Well, we've got one of those right here. 117 118 00:10:57,920 --> 00:11:01,380 Our WeatherData is a Decodable type. 118 119 00:11:01,690 --> 00:11:09,810 So notice how in this case, it's expecting a type in here as the input, not an object. 119 120 00:11:09,910 --> 00:11:20,500 So to specify the weatherData type, rather than just the weatherData object, we have to add a ".self" 120 121 00:11:20,860 --> 00:11:22,930 to reference the type. 121 122 00:11:22,930 --> 00:11:31,820 So if I click on this fix button, it turns my WeatherData into a data type that I'm passing in. 122 123 00:11:32,230 --> 00:11:39,460 Now, finally, the data that we want to encode is going to be passed in as the last input and that is going 123 124 00:11:39,460 --> 00:11:42,260 to come from this weatherData right here. 124 125 00:11:42,280 --> 00:11:45,550 So that's what I'm going to put there. 125 126 00:11:45,580 --> 00:11:52,330 So, now we should have decoded our data. But we're still getting errors because it's telling us that this 126 127 00:11:52,450 --> 00:12:00,780 call to decode can throw but is not marked with a 'try' and the error is not handled. 127 128 00:12:00,820 --> 00:12:01,570 What does that mean? 128 129 00:12:01,750 --> 00:12:08,500 Well, if we take a look at this decode method again, you can see that it's marked with this "throws" keyword 129 130 00:12:08,980 --> 00:12:14,590 which means that if something goes wrong, it can throw out an error. 130 131 00:12:14,680 --> 00:12:19,310 And so instead of simply just calling it as we would with other methods, 131 132 00:12:19,510 --> 00:12:24,310 all we have to do is we have to market with a "try" keyword. 132 133 00:12:24,610 --> 00:12:29,650 And in addition, we should really wrap it inside a block. 133 134 00:12:29,680 --> 00:12:30,940 That's called a "do" block. 134 135 00:12:30,950 --> 00:12:40,150 So the "do" block has the thing with the "try," and that marks the method which can throw an error. 135 136 00:12:40,690 --> 00:12:45,990 But if it does throw an error, we have a catch block that can catch the error. 136 137 00:12:46,060 --> 00:12:56,120 So we could simply print the error in here. So now our error goes away and Xcode is now happy with the 137 138 00:12:56,120 --> 00:12:59,330 way that we're programming our project. 138 139 00:12:59,330 --> 00:13:04,660 The final thing we have to do is that decode actually has an output, 139 140 00:13:04,820 --> 00:13:10,260 so it's going to create a WeatherData object. 140 141 00:13:10,370 --> 00:13:17,150 Let's go ahead and capture that in a constant. We'll call it decoded data and we'll set it to the output 141 142 00:13:17,360 --> 00:13:19,250 of this method call. 142 143 00:13:19,580 --> 00:13:27,800 And then there's decoded data because it has the data type of our WeatherData which means that it has 143 144 00:13:27,800 --> 00:13:29,560 the property name. 144 145 00:13:29,930 --> 00:13:36,830 Well, then we can actually print out decodedData.name. 145 146 00:13:36,830 --> 00:13:38,780 Now, let's go ahead and run our app. 146 147 00:13:42,840 --> 00:13:52,050 And if I go ahead and type in the name of a city, say, "Belgrade," and hit enter, you can see that the name 147 148 00:13:52,050 --> 00:13:58,930 of the city is being printed, but it's not being printed from my WeatherViewController. 148 149 00:13:58,990 --> 00:14:03,450 There is no print statements in my text field delegate methods. 149 150 00:14:03,450 --> 00:14:09,250 In fact, the only one that's being triggered is this decodedData.name. 150 151 00:14:09,390 --> 00:14:14,850 So some of you might be thinking, well, you could be cheating," that might still be somehow coming from 151 152 00:14:14,880 --> 00:14:16,230 the text field. 152 153 00:14:16,230 --> 00:14:21,890 Show me a piece of data that comes from the API that we didn't enter into the app ourselves. 153 154 00:14:22,790 --> 00:14:23,350 Okay. 154 155 00:14:23,370 --> 00:14:25,720 So I'm always up for a challenge. 155 156 00:14:25,800 --> 00:14:29,770 So if we take a look at our result that we get back, 156 157 00:14:29,940 --> 00:14:34,510 notice how we're getting the temperature of the location back as well. 157 158 00:14:34,530 --> 00:14:36,790 Let's try and get hold of the temperature. 158 159 00:14:36,990 --> 00:14:44,460 Now, a really handy thing that the JSON Awesome plugin can do is when you select one of these properties 159 160 00:14:44,490 --> 00:14:51,030 by clicking on it, you can click on this green button that comes up and copy the path that it would take 160 161 00:14:51,120 --> 00:14:53,780 to reach this value. 161 162 00:14:53,790 --> 00:15:01,230 So, now inside here instead of decodedData.name, I'm going to delete the name and I'm going to paste 162 163 00:15:01,560 --> 00:15:03,270 what I copied over from JSON 163 164 00:15:03,270 --> 00:15:04,240 Awesome. 164 165 00:15:04,320 --> 00:15:12,160 So it's telling me that in order to get to the temperature, I have to take the entire piece of data, 165 166 00:15:12,160 --> 00:15:20,050 go to the main property, and in the main property, go to the property temp in order to get that temperature. 166 167 00:15:20,590 --> 00:15:23,800 And that is what the entire path would look like. 167 168 00:15:24,340 --> 00:15:29,710 But right now, we haven't defined these properties in all WeatherData. 168 169 00:15:29,770 --> 00:15:31,120 So let's go ahead and do that 169 170 00:15:31,120 --> 00:15:33,250 to make these errors go away. 170 171 00:15:33,850 --> 00:15:41,920 Firstly, we've got the top level which comes from our WeatherData and the top level property name is 171 172 00:15:41,920 --> 00:15:43,230 called "main." 172 173 00:15:43,420 --> 00:15:46,330 So that's going to be what we'll add in here. 173 174 00:15:46,330 --> 00:15:47,060 Main. 174 175 00:15:47,200 --> 00:15:49,540 But what data type is it going to have? 175 176 00:15:49,540 --> 00:15:58,030 Well, it's actually a object with five items, and that object has these properties: temp, pressure, humidity, 176 177 00:15:58,090 --> 00:15:59,110 et cetera. 177 178 00:15:59,260 --> 00:16:05,400 That means we actually need another struct which I'm just going to call Main. 178 179 00:16:05,770 --> 00:16:08,990 And this, again, has to be Decodedable. 179 180 00:16:09,250 --> 00:16:14,000 And then, this main is the one that's going to have that property temp. 180 181 00:16:14,680 --> 00:16:19,570 And remember that when you're creating these properties, it's a little bit different from how we would 181 182 00:16:19,570 --> 00:16:20,080 do it 182 183 00:16:20,200 --> 00:16:27,280 normally when it's entirely all code. We can't just name these property names whatever we want. 183 184 00:16:27,280 --> 00:16:34,440 For example, if I call this temperature, then this decoding process is not going to work, 184 185 00:16:34,540 --> 00:16:40,390 so I have to make sure that my property names match the names of the properties that I'm seeing in my 185 186 00:16:40,390 --> 00:16:41,580 JSON data 186 187 00:16:41,770 --> 00:16:43,490 precisely. 187 188 00:16:43,960 --> 00:16:48,790 So this temp that I get back is a number with decimal places. 188 189 00:16:48,850 --> 00:16:57,680 So let's make that a Double data type. And now that we've created this Main struct, we can use it here 189 190 00:16:57,890 --> 00:17:00,890 as the data type of the main property. 190 191 00:17:00,890 --> 00:17:02,810 So let's add that right there. 191 192 00:17:03,410 --> 00:17:11,540 Now, this error goes away, but the error inside the Weather Manager also goes away because our decoded 192 193 00:17:11,540 --> 00:17:19,310 data which is of data type weatherData, now has a property called Main which holds a Main data type, 193 194 00:17:19,820 --> 00:17:21,920 which has a property of temp. 194 195 00:17:22,070 --> 00:17:30,380 So three steps to get to the temperature. But if we go ahead and run our app and I type in, let's see 195 196 00:17:30,380 --> 00:17:37,590 what the weather's like in Paris again, hit Enter. You can see that I'm getting the temperature printed 196 197 00:17:37,590 --> 00:17:42,000 now from our decodedData.main.temp. 197 198 00:17:42,000 --> 00:17:45,300 And in Paris, it's a lot nicer than in London 198 199 00:17:45,300 --> 00:17:50,300 as usual. So now for the final thing that we want, 199 200 00:17:50,320 --> 00:17:54,960 what if we wanted to get a hold of this description right here, 200 201 00:17:55,000 --> 00:18:00,250 how would you go about getting it using our JSON decoder? 201 202 00:18:00,280 --> 00:18:03,760 So this is going to be set as a challenge for you. 202 203 00:18:03,790 --> 00:18:11,410 Take a look at the data in Chrome using the URL and using the JSON Awesome tool to get the path 203 204 00:18:11,830 --> 00:18:14,770 of this particular description. 204 205 00:18:14,770 --> 00:18:25,030 Remember that this weather property holds data inside an array, and that's my hint to you for making 205 206 00:18:25,030 --> 00:18:26,050 this work. 206 207 00:18:26,200 --> 00:18:32,620 Try and get this description printed when we request for the data in our text field for a particular 207 208 00:18:32,620 --> 00:18:35,810 city name, and pause the video and try and give it a go now. 208 209 00:18:35,820 --> 00:18:38,760 All right. 209 210 00:18:38,770 --> 00:18:44,590 So the first thing I'm gonna do is I'm going to copy the path and, again, I'm going to replace 210 211 00:18:44,590 --> 00:18:47,560 my main.temp with whatever I copied over. 211 212 00:18:47,560 --> 00:18:54,580 So in this case, it's going to be from our decoded data going to go straight to the weather property. 212 213 00:18:55,030 --> 00:19:01,490 And then within the weather property where I've got a array with a single item, 213 214 00:19:01,630 --> 00:19:05,540 well, I'm going to get the first item in that array. 214 215 00:19:05,650 --> 00:19:14,410 So, now inside this array's first item, I've got a object that has a property name of description, so then 215 216 00:19:14,440 --> 00:19:16,480 description goes in at the end, 216 217 00:19:16,480 --> 00:19:19,630 and that's how I'm gonna get hold of that description. 217 218 00:19:19,660 --> 00:19:27,620 So, now all we have to do is to map that structure in our WeatherData file. 218 219 00:19:27,730 --> 00:19:32,960 The first thing we have is a property at the top level called weather. 219 220 00:19:33,130 --> 00:19:37,550 So I'm going to create a property called weather that matches that exactly. 220 221 00:19:37,720 --> 00:19:44,710 Next, I'm going to create my weather property which is going to be a WeatherData type. And just like 221 222 00:19:44,710 --> 00:19:49,190 the Main data type, we have to create a new object. 222 223 00:19:49,270 --> 00:19:56,890 But this time, instead of simply just having a weather struct as the value of the weather property, 223 224 00:19:56,950 --> 00:20:00,800 it's actually an array of weather items, 224 225 00:20:00,880 --> 00:20:01,860 right? 225 226 00:20:01,960 --> 00:20:05,920 So the weather property holds an array. 226 227 00:20:06,010 --> 00:20:08,090 How can I represent that? 227 228 00:20:08,110 --> 00:20:13,510 Well, I can go ahead and simply wrap this inside a set of square brackets. 228 229 00:20:13,510 --> 00:20:25,190 Now, I can create my weather structure which has a property called description. And so here let's create 229 230 00:20:25,220 --> 00:20:33,620 our description property which is going to be a string, and make sure that our Weather struct 230 231 00:20:33,710 --> 00:20:37,120 is, again, Decodable for our JSON decoder. 231 232 00:20:38,090 --> 00:20:47,570 Now, if we go ahead and run our code, then the errors go away. And let's check the weather for Beijing. 232 233 00:20:49,180 --> 00:20:57,070 And you can see that in Beijing there is clear skies all around and we're getting that through decoding 233 234 00:20:57,310 --> 00:21:06,220 our JSON data using the JSONDecoder from Swift, and we formatted the data using these Decoable 234 235 00:21:06,220 --> 00:21:07,480 struct, 235 236 00:21:07,480 --> 00:21:12,590 and finally, we're printing it out. If it's still confusing, 236 237 00:21:12,640 --> 00:21:19,840 I recommend just taking a look at your JSON, trying to get hold of different values from this JSON, 237 238 00:21:20,200 --> 00:21:26,840 and having a practice by adding more structs and properties. But in the next lesson, we're going to use 238 239 00:21:26,840 --> 00:21:34,840 our decoded data and format the data so that we can put it into our UI. For all of that and more, 239 240 00:21:34,850 --> 00:21:35,830 I'll see you on the next lesson.