Clojure新手技术求助:从JSON文件数组提取嵌套数据与键列表
Clojure新手JSON处理指南:提取键列表与嵌套数据
嘿,作为Clojure新手,这两个JSON处理任务其实是日常开发里的高频操作,我来一步步给你拆解清楚~
首先明确前提:你已经把目录里的JSON文件通过slurp读成了字符串数组,接下来需要先把这些字符串解析成Clojure的原生数据结构(比如map、vector),我们会用到clojure.data.json库来做解析。
第一步:准备工作(依赖与数据加载)
首先确保你的项目里引入了JSON解析依赖,如果是Leiningen的project.clj,加上这一行:
[org.clojure/data.json "2.4.0"]
然后加载目录下的所有JSON文件并解析:
(require '[clojure.data.json :as json]) (require '[clojure.java.io :as io]) ;; 读取指定目录下的所有JSON文件,解析为Clojure数据结构 (def invoice-files (->> (io/file "./your-invoice-directory") ;; 替换成你的JSON文件目录 file-seq (filter #(.isFile %)) (map slurp) (map json/read-string)))
任务1:提取JSON的键列表
从你的示例结构看,单个JSON文件解析后是一个vector,里面包含一个发票map。我们需要先取到这个map,再提取它的顶层键。
单个发票的键列表
如果只处理单个文件的数据:
;; 假设single-file-data是单个解析后的JSON数据 (def single-file-data (first invoice-files)) (def top-level-keys (keys (first single-file-data))) ;; 输出会是(:id :lines :date :total :invoice-ad...)
批量处理所有文件的键列表
如果要处理所有文件的发票键列表,用map遍历即可,同时用some->避免空数组的情况(防止报错):
(def all-invoice-keys (map #(some-> % first keys) invoice-files))
解释:some->会依次执行每个步骤,如果中间某一步返回nil(比如某个文件是空数组),就直接返回nil,不会抛出NullPointerException
任务2:提取嵌套数据
嵌套数据的核心是通过关键字(keyword)逐层访问map,结合map、mapcat等函数批量处理。以下是几个常见场景的示例:
场景1:提取每个发票的ID、日期和总金额
(def invoice-summary (map (fn [file-data] (let [invoice (first file-data)] ;; 取文件中的发票对象 {:id (:id invoice) :date (:date (:date invoice)) ;; 嵌套访问date里的date字段 :total-GBP (:GBP (:total invoice))})) ;; 取total里的GBP金额 invoice-files))
场景2:提取所有商品行的描述与价格
如果要把所有文件里的商品行(lines)都提取出来合并成一个列表,用mapcat(相当于先map再concat):
(def all-line-items (mapcat (fn [file-data] (let [invoice (first file-data)] (map (fn [line] {:description (:description line) :price-GBP (:GBP (:price line))}) (:lines invoice)))) ;; 遍历当前发票的所有lines invoice-files))
场景3:提取特定条件的嵌套数据
比如只想提取总金额大于20的发票信息:
(def high-value-invoices (filter (fn [file-data] (let [invoice (first file-data) total (:GBP (:total invoice))] (> total 20))) invoice-files))
小技巧提醒
- 如果你不确定某个嵌套路径是否存在,可以用
get-in函数,它支持默认值:;; 如果:total里没有:GBP,返回0而不是nil (get-in invoice [:total :GBP] 0) - 对于复杂的JSON结构,推荐用
clojure.walk里的函数来递归处理,比如walk、postwalk。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

