WEBVTT 1 00:00:00.470 --> 00:00:01.660 Hi and welcome back. 2 00:00:01.660 --> 00:00:05.240 In this video, we're going to turn our CSVs into JSON 3 00:00:05.240 --> 00:00:06.570 just for us to understand a bit better 4 00:00:06.570 --> 00:00:08.900 how that works, and whether there's any benefits 5 00:00:08.900 --> 00:00:10.803 to using JSON instead of CSV. 6 00:00:11.890 --> 00:00:14.040 Often I find that JSON does give you 7 00:00:14.040 --> 00:00:17.560 a bit more flexibility and makes things a bit easier, 8 00:00:17.560 --> 00:00:19.560 just because it very easily translates 9 00:00:19.560 --> 00:00:22.230 into Python dictionaries, and also this just gives you 10 00:00:22.230 --> 00:00:25.080 a bit more exposure to how Python works. 11 00:00:25.080 --> 00:00:28.250 If you don't want to move this app over to JSON, 12 00:00:28.250 --> 00:00:29.700 feel free to just go into the next video, 13 00:00:29.700 --> 00:00:31.843 and we're gonna look at databases instead. 14 00:00:33.260 --> 00:00:35.500 First thing to do is to change our comment up here 15 00:00:35.500 --> 00:00:37.423 to say we are using JSON. 16 00:00:38.330 --> 00:00:41.703 Then I'm going to change the file to be books.json. 17 00:00:43.010 --> 00:00:46.763 And now we will begin using our 18 00:00:48.150 --> 00:00:50.723 interface here to create our files. 19 00:00:53.020 --> 00:00:55.650 Now when we create a book table, 20 00:00:55.650 --> 00:00:58.950 we are wanting to make sure the file is there, 21 00:00:58.950 --> 00:01:00.510 and we're going to change this later on, 22 00:01:00.510 --> 00:01:03.140 we're gonna get an error when we try to use this, 23 00:01:03.140 --> 00:01:05.253 but let's leave it like that just for now. 24 00:01:07.770 --> 00:01:12.110 Then, let's first implement the get_all_books function, 25 00:01:12.110 --> 00:01:13.630 because that's the easiest one. 26 00:01:13.630 --> 00:01:16.140 So, I'm going to delete all of this except 27 00:01:16.140 --> 00:01:19.120 the context manager, and all that we have to return 28 00:01:19.120 --> 00:01:22.700 is json.load of the file. 29 00:01:22.700 --> 00:01:25.050 Of course we'll have to import JSON at the top. 30 00:01:27.120 --> 00:01:30.960 Remember the JSON file is going to be a list, 31 00:01:30.960 --> 00:01:35.960 that does stuff and has maybe some books in here, 32 00:01:35.960 --> 00:01:38.800 there's like name is name, 33 00:01:38.800 --> 00:01:42.310 something like Clean Code, 34 00:01:42.310 --> 00:01:44.643 author is gonna be Robert, 35 00:01:45.550 --> 00:01:47.580 and read is going to be True. 36 00:01:47.580 --> 00:01:50.110 JSON can store true and false values, 37 00:01:50.110 --> 00:01:52.650 so feel free to store them directly in JSON, 38 00:01:52.650 --> 00:01:54.463 which simplifies things a little bit. 39 00:01:55.300 --> 00:01:59.380 So it's going to be a list of dictionaries, and that's cool. 40 00:01:59.380 --> 00:02:03.040 So when we get all the books, we do json.load, 41 00:02:03.040 --> 00:02:04.773 and that gives us a list. 42 00:02:05.860 --> 00:02:07.940 When we have our list, we can iterate over it 43 00:02:07.940 --> 00:02:10.060 and we can do everything that we could with a normal list, 44 00:02:10.060 --> 00:02:13.083 just pretend that it's this that we've put in a variable. 45 00:02:14.810 --> 00:02:17.750 So when we want to add a new book, 46 00:02:17.750 --> 00:02:19.093 how are we gonna do that? 47 00:02:20.930 --> 00:02:25.700 Well, we need somehow to open up the JSON file 48 00:02:25.700 --> 00:02:29.770 and write a new dictionary to it. 49 00:02:29.770 --> 00:02:32.290 Now it's no longer as simple as appending 50 00:02:32.290 --> 00:02:35.540 something at the end, because we have to append something 51 00:02:35.540 --> 00:02:38.260 between this curly bracket and this square bracket, 52 00:02:38.260 --> 00:02:40.323 something like this. 53 00:02:43.090 --> 00:02:45.030 So it's not so easy, so what I'm going to do 54 00:02:45.030 --> 00:02:47.310 is do the same thing that we did with marking books 55 00:02:47.310 --> 00:02:49.150 as read and deleting them, I'm going to 56 00:02:49.150 --> 00:02:51.410 open all the books, read them all, 57 00:02:51.410 --> 00:02:54.010 append one using Python and then save them all back. 58 00:02:55.700 --> 00:02:58.750 So, books is going to be get_all_books, 59 00:03:00.670 --> 00:03:02.970 then we're gonna do books, which remember, is a list, 60 00:03:02.970 --> 00:03:05.210 so we can do append to it, 61 00:03:05.210 --> 00:03:07.150 and then we're going to append a dictionary 62 00:03:07.150 --> 00:03:09.363 using the parameters that we got here, 63 00:03:13.130 --> 00:03:17.243 and it's going to start off as False for the read status. 64 00:03:18.250 --> 00:03:21.283 Of course, at the end we want to save all the books. 65 00:03:22.240 --> 00:03:24.560 And the books that we wanna save are the books 66 00:03:24.560 --> 00:03:26.053 that we've modified already. 67 00:03:27.000 --> 00:03:30.200 Now, this save_all_books function is defined down here, 68 00:03:30.200 --> 00:03:33.550 so we're gonna just cut it and move it 69 00:03:33.550 --> 00:03:35.880 down to save_all_books, but actually, 70 00:03:35.880 --> 00:03:37.853 apologies, get_all_books is used first, 71 00:03:39.260 --> 00:03:43.593 so we are going to put it here. 72 00:03:48.390 --> 00:03:49.223 There. 73 00:03:51.040 --> 00:03:55.000 So, we will put it there, and instead, of course, 74 00:03:55.000 --> 00:03:56.790 of doing all of this iteration, 75 00:03:56.790 --> 00:03:59.730 all we have to do in the save_all_books file function 76 00:03:59.730 --> 00:04:03.363 is json.dump books into file. 77 00:04:04.510 --> 00:04:05.990 And that's just gonna save everything 78 00:04:05.990 --> 00:04:09.273 as a JSON string instead of as a CSV. 79 00:04:10.970 --> 00:04:13.022 So now we've implemented our add_book, 80 00:04:13.022 --> 00:04:15.950 get_all_books and save_all_books functions. 81 00:04:15.950 --> 00:04:19.340 We can go ahead and mark the book as read, 82 00:04:19.340 --> 00:04:21.810 but you may realise that we don't actually 83 00:04:21.810 --> 00:04:26.360 have to do anything except turn this one into a True, 84 00:04:26.360 --> 00:04:28.623 which is everything that we need to do. 85 00:04:29.460 --> 00:04:31.320 Similarly for the delete_book, 86 00:04:31.320 --> 00:04:32.760 we're getting all the books, now they're coming 87 00:04:32.760 --> 00:04:35.070 from the JSON file, saving all the books, 88 00:04:35.070 --> 00:04:36.550 they're going to a JSON file, 89 00:04:36.550 --> 00:04:38.180 and in the middle, we're just modifying 90 00:04:38.180 --> 00:04:40.570 the list so that it doesn't include 91 00:04:40.570 --> 00:04:41.900 the book that matches the name, 92 00:04:41.900 --> 00:04:43.950 again, we don't have to do anything here. 93 00:04:45.560 --> 00:04:47.260 Pretty nice, eh? 94 00:04:47.260 --> 00:04:49.480 Not a lot has changed, but the only thing 95 00:04:49.480 --> 00:04:52.200 that's changed is the False, and zero and one, 96 00:04:52.200 --> 00:04:53.963 so if we go over to our app.py, 97 00:04:55.160 --> 00:04:58.260 we can go down here and just remove this if book read 98 00:04:58.260 --> 00:05:01.360 equal equal one, change it to if book read. 99 00:05:01.360 --> 00:05:04.063 Since that already assumes is true. 100 00:05:05.660 --> 00:05:08.810 And that's it, we can then press play, 101 00:05:08.810 --> 00:05:10.723 and start adding books. 102 00:05:11.710 --> 00:05:14.530 And I said earlier this is gonna raise an error, 103 00:05:14.530 --> 00:05:17.360 so I am going to enter a new book name, 104 00:05:17.360 --> 00:05:21.670 this is gonna be Python 101 by Jose Salvatierra, 105 00:05:21.670 --> 00:05:23.220 this doesn't exist, by the way. 106 00:05:24.120 --> 00:05:25.633 Oh, we get the error. 107 00:05:26.790 --> 00:05:28.460 So this is the error I was talking about earlier, 108 00:05:28.460 --> 00:05:32.413 and it says json.decoder.JSONdecodeerror. 109 00:05:33.980 --> 00:05:38.550 Expecting a value in line one column one character zero. 110 00:05:38.550 --> 00:05:41.520 Okay, so it was expecting a value, let's see 111 00:05:41.520 --> 00:05:43.413 what the books.json file says. 112 00:05:44.710 --> 00:05:46.853 It's completely empty, nothing there. 113 00:05:48.250 --> 00:05:50.210 Okay, so the error says it was expecting a value, 114 00:05:50.210 --> 00:05:52.380 and evidently it didn't find one. 115 00:05:52.380 --> 00:05:54.123 So why was it expecting a value? 116 00:05:55.320 --> 00:05:57.810 Well, here you can see the line that raised 117 00:05:57.810 --> 00:06:01.030 the JSON decode error, it's not something we wrote, 118 00:06:01.030 --> 00:06:03.800 it's inside this decoder.py file, 119 00:06:03.800 --> 00:06:06.870 and now we're getting lines that we didn't write, 120 00:06:06.870 --> 00:06:09.860 because of course we're using a module that we didn't write, 121 00:06:09.860 --> 00:06:11.873 and this is the module that raised the error. 122 00:06:13.400 --> 00:06:17.090 That error then appeared in this raw decode function, 123 00:06:17.090 --> 00:06:19.000 so that's the next thing we get, 124 00:06:19.000 --> 00:06:21.900 that was called from this decode function, 125 00:06:21.900 --> 00:06:24.110 which was here, and then here, 126 00:06:24.110 --> 00:06:28.227 and eventually we reach our code, return json.load(file). 127 00:06:29.340 --> 00:06:32.900 And that was inside the get_all_books file, that function. 128 00:06:32.900 --> 00:06:37.550 So let's go over there, and let's make this a bit smaller, 129 00:06:37.550 --> 00:06:39.970 and it's saying that the error was returned here, 130 00:06:39.970 --> 00:06:41.423 return json.load. 131 00:06:43.410 --> 00:06:46.453 Why do you think there may be an error in this line? 132 00:06:47.660 --> 00:06:49.380 Not sure what you came up with, 133 00:06:49.380 --> 00:06:53.610 but the problem here is that our books.json file 134 00:06:53.610 --> 00:06:56.033 is empty, and that's not valid JSON. 135 00:06:57.430 --> 00:06:59.430 Remember I said that some programmes would expect 136 00:06:59.430 --> 00:07:02.303 your JSON file to have an object around it, 137 00:07:03.600 --> 00:07:06.020 some will allow a list to be in it, 138 00:07:06.020 --> 00:07:07.980 and Python's JSON module is one of these 139 00:07:07.980 --> 00:07:09.920 that allow the list, and that's totally valid, 140 00:07:09.920 --> 00:07:11.013 totally valid JSON. 141 00:07:12.150 --> 00:07:13.920 There's a few more things that it can be, 142 00:07:13.920 --> 00:07:15.440 but it certainly cannot be empty, 143 00:07:15.440 --> 00:07:16.983 for that is not valid JSON. 144 00:07:17.990 --> 00:07:19.870 So what we have to do is make sure 145 00:07:19.870 --> 00:07:21.970 that in the create_book_table 146 00:07:21.970 --> 00:07:24.333 we are initialising it to some value. 147 00:07:25.720 --> 00:07:28.100 So what we're going to do, is we are going to say 148 00:07:28.100 --> 00:07:30.710 that the initial value has to be 149 00:07:33.870 --> 00:07:34.923 an empty list. 150 00:07:38.460 --> 00:07:41.500 And then we'll need the variable up here as well, of course. 151 00:07:41.500 --> 00:07:43.570 Now, as soon as we create the book table, 152 00:07:43.570 --> 00:07:46.650 it's going to initialise the list's value to be an empty, 153 00:07:46.650 --> 00:07:49.340 sorry, the file's value to be an empty list, 154 00:07:49.340 --> 00:07:51.950 and then when we go over to add a book 155 00:07:51.950 --> 00:07:54.530 and we get all the books, what it's gonna do, 156 00:07:54.530 --> 00:07:57.180 is it's going to read that empty list, 157 00:07:57.180 --> 00:07:59.760 and then it's going to append to it. 158 00:07:59.760 --> 00:08:01.810 And then it's gonna save it back. 159 00:08:01.810 --> 00:08:03.880 Now that we'll have some valid JSON in there, 160 00:08:03.880 --> 00:08:04.930 let's run this again. 161 00:08:08.726 --> 00:08:10.940 And you can see that it works. 162 00:08:10.940 --> 00:08:13.310 And this book, by the way, 30 Days of Python, 163 00:08:13.310 --> 00:08:15.430 is coming soon, so if you do know somebody 164 00:08:15.430 --> 00:08:18.743 that is interested in 30 Days of Python, lemme know. 165 00:08:19.640 --> 00:08:21.463 So now we've got our two books here. 166 00:08:22.610 --> 00:08:25.330 And as you can see, we've not read them, 167 00:08:25.330 --> 00:08:27.570 not read them, doesn't exist yet, of course, 168 00:08:27.570 --> 00:08:29.983 but then we can mark one as read, 169 00:08:32.640 --> 00:08:34.380 and listing them again now shows that 170 00:08:34.380 --> 00:08:36.440 one of them is not read and the other one is read. 171 00:08:36.440 --> 00:08:40.060 Looking into books.json, we can see that 172 00:08:40.060 --> 00:08:44.680 the JSON stored here represents what we're seeing there. 173 00:08:44.680 --> 00:08:49.310 Two objects, Python 101 by me, read is false, 174 00:08:49.310 --> 00:08:51.140 and another object, 30 Days of Python by me, 175 00:08:51.140 --> 00:08:52.670 and read is true. 176 00:08:52.670 --> 00:08:56.340 Notice how when you call your file .json in Python, 177 00:08:56.340 --> 00:08:58.710 it starts giving you some nice syntax highlighting. 178 00:08:58.710 --> 00:09:00.490 So that's pretty nice, too. 179 00:09:00.490 --> 00:09:02.900 And also notice how the false with a capital F 180 00:09:02.900 --> 00:09:05.140 went down to a lowercase f, 181 00:09:05.140 --> 00:09:07.790 and the true with a capital T went down to a lowercase t. 182 00:09:07.790 --> 00:09:10.130 That's because these are the JavaScript equivalents 183 00:09:10.130 --> 00:09:12.940 of Python's True and False with capital letters, 184 00:09:12.940 --> 00:09:14.880 in JavaScript they have lowercase letters, 185 00:09:14.880 --> 00:09:17.170 JSON means JavaScript Object Notation, 186 00:09:17.170 --> 00:09:20.440 so of course it's gonna go down to lowercase as well. 187 00:09:20.440 --> 00:09:22.280 That's it, we can delete books, 188 00:09:22.280 --> 00:09:25.200 we can delete Python 101, since that one's not happening, 189 00:09:25.200 --> 00:09:27.890 list them again, that's now like that, 190 00:09:27.890 --> 00:09:30.663 and of course we can quit and that exits. 191 00:09:32.770 --> 00:09:35.580 So that's how you would turn a programme from CSVs 192 00:09:35.580 --> 00:09:38.390 over to JSON, and all we've had to do, 193 00:09:38.390 --> 00:09:41.690 modify a couple of functions to tell our code 194 00:09:41.690 --> 00:09:45.030 now to talk to a JSON instead of saving things 195 00:09:45.030 --> 00:09:47.800 manually as strings into the file. 196 00:09:47.800 --> 00:09:49.850 Pretty straightforward, and our app.py 197 00:09:49.850 --> 00:09:51.840 hasn't had to change basically at all, 198 00:09:51.840 --> 00:09:53.333 other than this if there. 199 00:09:55.020 --> 00:09:56.890 So that's it for this video, hope you learned something, 200 00:09:56.890 --> 00:09:58.897 and I'll see you on the next one.