从JSON文件数组中检索嵌套数据

时间:2018-04-17 17:06:00

标签: json clojure

我是Clojure的新手并尝试从JSON中检索密钥列表。 初始数据结构是一个从目录中悄悄出现的JSON文件数组,下面是其中一个文件的示例(因此它实际上是以下列表):

study(title='gap detector', overlay=true)

//plotshape(<condition>, <options>) // condition must be true to plot something

is_percentage_increase = if (close-close[1])/close[1] > 0.05
    true
plotshape(is_percentage_increase, style=shape.circle, color=green)

我需要获得一个&#34;描述&#34;价值除了&#34;交货&#34;,只是&#34; SKU-1074 x 1&#34;对于每个文件中的每个订单。然后我在另一个函数中使用此列表链接到产品ID。 我之前已经完成了半实现,但它似乎没有迭代所有内容只有一个订单,我编辑的以下代码试图实现这一点:

[
    {
        "id": "d588596f-c8ce-41de-85f6-12321a2e1888",
        "lines": [
            {
                "description": "SKU-1079 x 1",
                "price": {
                    "GBP": 14.99
                }
            },
            {
                "description": "Delivery",
                "price": {
                    "GBP": 3.49
                }
            }
        ],
        "date": {
            "date": "2016-09-07T00:53:31.000Z"
        },
        "total": {
            "GBP": 18.48
        },
        "invoice-address": [
            "93",
            "Westhorpe Road",
            "Inverness",
            "IV1 3WU"
        ],
        "delivery-address": [
            "93",
            "Westhorpe Road",
            "Inverness",
            "IV1 3WU"
        ]
    },
    {
        "id": "f1f471b2-5bf7-404e-9345-dcccdfba5c8a",
        "lines": [
            {
                "description": "SKU-1003 x 1",
                "price": {
                    "GBP": 14.99
                }
            },
            {
                "description": "SKU-1015 x 1",
                "price": {
                    "GBP": 14.99
                }
            },
            {
                "description": "SKU-1086 x 1",
                "price": {
                    "GBP": 14.99
                }
            },
            {
                "description": "SKU-1029 x 1",
                "price": {
                    "GBP": 14.99
                }
            },
            {
                "description": "SKU-1074 x 1",
                "price": {
                    "GBP": 14.99
                }
            },
            {
                "description": "Delivery",
                "price": {
                    "GBP": 3.49
                }
            }
        ],
        "date": {
            "date": "2016-09-07T01:15:48.000Z"
        },
        "total": {
            "GBP": 78.44
        },
        "invoice-address": [
            "18",
            "Barbican",
            "East Central London",
            "EC17 4HP"
        ],
        "delivery-address": [
            "18",
            "Barbican",
            "East Central London",
            "EC17 4HP"
        ]
    }
]

尝试了很多代码的迭代,主要是使用嵌套映射,for和匿名函数,但我似乎总是返回的是一个nil值列表。

以下从ordersData地图中检索第一个订单的行,但我无法理解如何在此级别进行迭代。在命令式语言中,我可能使用嵌套循环但不完全确定。

(defn getOrders [year month day]
  (let [fs (filter #(.isFile %) (file-seq (clojure.java.io/file (str "data/orders/" year "/" month "/" day))))
        ordersData (map #(json/read-str (slurp %) :key-fn keyword) fs)
        getLines (fn [x] (map :lines x))
        getDescription (fn [x] (map #(get % :description)))]
        ;(for [x (map #(getLines %) ordersData)] (remove #{"Delivery"} (map #(get % :description) x)))
        (->>  (for [x ordersData] (for [y x] (for [z y] z)))
              (map (fn [x] (map (fn [y] y) x))) ;Tried many different maps/fors here
        )
  )
)

1 个答案:

答案 0 :(得分:2)

这是一种相当简单的方法:

(def my-maps (json/read-str "json goes here"))

定义一个将在JSON中的每个顶级地图上运行的函数:

(defn descriptions [m]
  (->> (get m "lines")              ;; get the lines from the map
       (map #(get % "description")) ;; get the description values
       (remove #{"Delivery"})))     ;; remove any "Delivery" values

这个descriptions函数可能更有效,但我认为这是一个很好的解释性示例。

然后{J}映射的map

(map descriptions my-maps)
=> (("SKU-1079 x 1")
    ("SKU-1003 x 1" "SKU-1015 x 1" "SKU-1086 x 1" "SKU-1029 x 1" "SKU-1074 x 1"))

要获得您想要的完全平坦的列表,请将map替换为mapcat

(mapcat descriptions my-maps)
=> ("SKU-1079 x 1" "SKU-1003 x 1" "SKU-1015 x 1" "SKU-1086 x 1" "SKU-1029 x 1" "SKU-1074 x 1")