【问题标题】:Iterating over a json array of objects in Clojure在 Clojure 中迭代一个 json 对象数组
【发布时间】:2018-10-20 13:18:37
【问题描述】:

我将使用 Clojure 实现一个 RESTful API。对于 GET 请求,有一个诸如 /List 之类的 url,我想从下面的纯数据(即 json 文件)返回解析后的响应。 获取请求:

(GET "/list/:from-date/:to-date" [from-date to-date]
      wrap-json-response (response (parse-object from-date to-date all-records)))

如您所见,需要有两个查询参数from-dateto-date。我需要的是一个名为parse-object 的函数,它解析纯数据并将update-datefrom-dateto-date 进行比较。如果update-date 介于这两个参数之间,则以预期的对象结构返回它。 下面是具有给定数据的纯对象和预期对象结构。

纯数据(data.json):

[{"name": "JOHN",
  "update-date": "2017-11-10",
  "role": "admin"},
 {"name": "CHRIS",
  "update-date": "2018-04-28",
  "role": "user"},
 {"name": "ANNIE",
  "update-date": "2018-03-11",
  "role": "admin"}]

给定参数:from-date: 2017-11-01 to-date: 2018-04-28

预期的返回响应:

{"users":[
     {"role":"admin",
      "shows":[
            {"name":"JOHN",
             "status":"active"}]},
      {"role":"user",
       "shows":[
            {"name":"CHRIS",
             "status":"active"}]}]}

【问题讨论】:

  • 到目前为止你有什么尝试?

标签: json clojure clojurescript reagent


【解决方案1】:

您可以使用像 Cheshire (https://github.com/dakrone/cheshire) 这样的库在 Clojure 中进行 JSON 解析/打印。

您可以使用filter 函数过滤数据:

(filter (fn [{:strs [update-date]}]
          (not (or (.before update-date from-date)
                   (.after update-date to-date))))
        objects)

您可以使用group-by 重塑数据:

(group-by (fn [{:strs [role]}]
            role)
          objects)

并使用for 表达式:

(for [[k xs] groups]
  {"role" k
   "shows" (for [x xs]
             (select-keys x ["name" "status"]))})

【讨论】:

  • 对不起,我对 Clojure 有点陌生。我正在使用 data.json 来处理 JSON 文件。你为什么使用 .before.after 作为日期,即使它们是字符串。
  • 嗨,Sepehr;我在这里假设您会将它们解析为 java.time Instants 以进行比较。您也可以仅依靠现有的日期格式来进行字符串比较(compare "abc" "def")
【解决方案2】:

这里是你如何做到这一点的大纲。我会把最终的格式留给你。

(ns tst.demo.core
  (:use tupelo.core demo.core tupelo.test)
  (:require
    [tupelo.string :as tstr] )
  (:import [java.time LocalDate]))

(def data-json
  "[{'name' : 'JOHN',
     'update-date' : '2017-11-10',
    'role' : 'admin'},
   {'name' : 'CHRIS',
     'update-date' : '2018-04-28',
    'role' : 'user'},
   {'name' : 'ANNIE',
    'update-date' : '2018-03-11',
    'role' : 'admin'}] ")

(dotest
  (let
    [date-from (LocalDate/parse "2017-11-01")
     date-to   (LocalDate/parse "2018-04-28")
     data-edn  (json->edn (tstr/quotes->double data-json))
     data-keep (vec
                 (remove nil?
                   (for [user-rec data-edn]
                     (let [update-date (LocalDate/parse (grab :update-date user-rec))]
                       (when (and
                               (.isBefore date-from update-date)   ; may need to add .isEqual
                               (.isAfter  date-to   update-date))  ; may need to add .isEqual
                         user-rec)))))]
    (spyx-pretty data-keep)))

结果:

---------------------------------------------
   Clojure 1.10.0-alpha8    Java 1.8.0_161
---------------------------------------------

Testing tst.demo.core
data-keep => 
[{:name "JOHN",  :update-date "2017-11-10", :role "admin"}
 {:name "ANNIE", :update-date "2018-03-11", :role "admin"}]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-30
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多