The JSON data is in the following format
{
"Genesis": {
"1": {
"1": "In the beginning..." ,
"2": "..."
},
"2": { ... }
},
"Exodus": { ... },
...
}
In JSON, keys aren't ordered and must be strings.
The goal is to parse the JSON file, order everything correctly (which means parsing the keys into integers), and produce an array that looks like this:
[
("Genesis", 1, 1, "In the beginning..")
("Genesis", 1, 2, "")
]
The data structure can be a tuple or some new type.
(ns versify.core
(:require [cheshire.core :refer :all])
(:gen-class))
(def book-order ["Genesis", "Exodus", "Leviticus", "Numbers", "Deuteronomy",
"Joshua", "Judges", "Ruth", "1 Samuel", "2 Samuel", "1 Kings", "2 Kings",
"1 Chronicles", "2 Chronicles", "Ezra", "Nehemiah", "Esther", "Job",
"Psalms", "Proverbs", "Ecclesiastes", "Song of Solomon", "Isaiah",
"Jeremiah", "Lamentations", "Ezekiel", "Daniel", "Hosea", "Joel", "Amos",
"Obadiah", "Jonah", "Micah", "Nahum", "Habakkuk", "Zephaniah", "Haggai",
"Zechariah", "Malachi", "Matthew", "Mark", "Luke", "John", "Acts",
"Romans", "1 Corinthians", "2 Corinthians", "Galatians", "Ephesians",
"Philippians", "Colossians", "1 Thessalonians", "2 Thessalonians",
"1 Timothy", "2 Timothy", "Titus", "Philemon", "Hebrews", "James",
"1 Peter", "2 Peter", "1 John", "2 John", "3 John", "Jude", "Revelation"])
(defn intify [m]
(apply assoc (sorted-map)
(mapcat
(fn [[k v]]
[(read-string k), v]) m)))
(defn get-books [bible]
(map (fn [book] [book, (bible book)]) book-order))
(defn get-chapters [books]
(mapcat (fn [[k v]]
(let [i (intify v)]
(map (fn [[n c]] [k, n, c]) i))) books))
(defn get-verses [verses]
(mapcat (fn [[b c d]]
(let [i (intify d)]
(map (fn [[v t]] [b, c, v, t]) i))) verses))
(def parse (comp get-verses get-chapters get-books))
(defn -main
[& args]
(let [bible (parse-string (slurp "ESV.json"))]
(first (parse bible))))
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Lens
import Data.Aeson
import Data.Aeson.Lens
import qualified Data.ByteString.Lazy.Char8 as BS
import Data.List (elemIndex, sortOn)
import qualified Data.Text as T
bookOrder = ["Genesis", "Exodus", "Leviticus", "Numbers", "Deuteronomy",
"Joshua", "Judges", "Ruth", "1 Samuel", "2 Samuel", "1 Kings", "2 Kings",
"1 Chronicles", "2 Chronicles", "Ezra", "Nehemiah", "Esther", "Job",
"Psalms", "Proverbs", "Ecclesiastes", "Song of Solomon", "Isaiah",
"Jeremiah", "Lamentations", "Ezekiel", "Daniel", "Hosea", "Joel", "Amos",
"Obadiah", "Jonah", "Micah", "Nahum", "Habakkuk", "Zephaniah", "Haggai",
"Zechariah", "Malachi", "Matthew", "Mark", "Luke", "John", "Acts",
"Romans", "1 Corinthians", "2 Corinthians", "Galatians", "Ephesians",
"Philippians", "Colossians", "1 Thessalonians", "2 Thessalonians",
"1 Timothy", "2 Timothy", "Titus", "Philemon", "Hebrews", "James",
"1 Peter", "2 Peter", "1 John", "2 John", "3 John", "Jude", "Revelation"]
main = do
Just obj <- decode <$> BS.readFile "ESV.json" :: IO (Maybe Value)
let bible = parseBible obj
print bible
parseBible obj =
(do (book, obj) <- obj ^@.. members
(chapter, obj) <- obj ^@.. members
(verse, String text) <- obj ^@.. members
return (book, readText chapter :: Int, readText verse :: Int, text))
& sortOn sortKey
where
readText = read . T.unpack
sortKey (book, chapter, verse, _) = (elemIndex book bookOrder, chapter, verse)