Assignment 7

HTML and JSON

Approach

This assignment compares the same three books (Cosmos, An Astronaut’s Guide to Life on Earth, and Welcome to the Universe) loaded from an HTML table and a JSON file into R data frames. I’ll hand-write both files, host them on GitHub, and load them by URL. The main challenge I anticipate is the authors column: JSON stores multiple authors as an array, while an HTML cell holds only text, so I’ll flatten the JSON array into a semicolon-separated string to match. I also expect smaller mismatches, like year loading as text from one source and a number from the other, or the two readers returning different object classes. I’ll inspect and standardize column names, order, and types before comparing, and if the data frames still differ, I’ll report exactly where.

Code Base

library(tidyverse)
Warning: package 'tidyverse' was built under R version 4.6.1
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.2.1     ✔ readr     2.2.0
✔ forcats   1.0.1     ✔ stringr   1.6.0
✔ ggplot2   4.0.3     ✔ tibble    3.3.1
✔ lubridate 1.9.5     ✔ tidyr     1.3.2
✔ purrr     1.2.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(rvest)

Attaching package: 'rvest'

The following object is masked from 'package:readr':

    guess_encoding
library(jsonlite)

Attaching package: 'jsonlite'

The following object is masked from 'package:purrr':

    flatten
html_url <- "https://raw.githubusercontent.com/daanishrasheed/DATA607/refs/heads/main/Assignment%207/books.html"
json_url <- "https://raw.githubusercontent.com/daanishrasheed/DATA607/refs/heads/main/Assignment%207/books.json"
books_html <- read_html(html_url) |>
  html_element("table") |>
  html_table()

books_html
# A tibble: 3 × 5
  title                                    authors  year publisher primary_focus
  <chr>                                    <chr>   <int> <chr>     <chr>        
1 Cosmos                                   Carl S…  1980 Random H… Bridges scie…
2 An Astronaut's Guide to Life on Earth    Chris …  2013 Little, … Shares lesso…
3 Welcome to the Universe: An Astrophysic… Neil d…  2016 Princeto… An accessibl…
books_json <- fromJSON(json_url)$books |>
  as_tibble() |>
  mutate(authors = map_chr(authors, \(a) str_c(a, collapse = "; ")))

books_json
# A tibble: 3 × 5
  title                                    authors  year publisher primary_focus
  <chr>                                    <chr>   <int> <chr>     <chr>        
1 Cosmos                                   Carl S…  1980 Random H… Bridges scie…
2 An Astronaut's Guide to Life on Earth    Chris …  2013 Little, … Shares lesso…
3 Welcome to the Universe: An Astrophysic… Neil d…  2016 Princeto… An accessibl…
identical(books_html, books_json)
[1] TRUE
all.equal(books_html, books_json)
[1] TRUE
tibble(
  column = names(books_html),
  html   = map_chr(books_html, \(x) class(x)[1]),
  json   = map_chr(books_json, \(x) class(x)[1])
)
# A tibble: 5 × 3
  column        html      json     
  <chr>         <chr>     <chr>    
1 title         character character
2 authors       character character
3 year          integer   integer  
4 publisher     character character
5 primary_focus character character

Conclusion

After turning the JSON authors array into a delimited string, the data frames output by each of the sources are completely the same in terms of column names, order, data types, and values. The only structural difference is that the JSON data structure handles the list of authors as an array, whereas the HTML data structure can hold just text inside a cell, requiring the delimiter.