【问题标题】:Retrieving nested data from array of JSON files从 JSON 文件数组中检索嵌套数据
【发布时间】:2018-04-20 05:54:21
【问题描述】:

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

[
    {
        "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"
        ]
    }
]

我需要为每个文件中的每个订单获取除“交付”之外的“描述”值的单一平面列表,只需“SKU-1074 x 1”。然后,我在另一个函数中使用此列表链接到产品 ID。 我之前已经半实现了这一点,但它似乎没有迭代所有内容,只使用以下代码进行了一个订单,我一直在编辑以尝试实现这一点:

(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
        )
  )
)

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

下面从 ordersData 映射中检索第一个订单的行,但我不明白如何在这个级别进行迭代。在命令式语言中,我可能会使用嵌套循环,但并不完全确定。

(get (first (first (getOrders "2017" "09" "07"))) :lines)

【问题讨论】:

    标签: json clojure


    【解决方案1】:

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

    (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 函数可能更高效,但我认为这是一个很好的解释性示例。

    然后map 在您的 JSON 映射上运行该函数:

    (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")
    

    【讨论】:

    • 我遇到的问题是使用它:ordersData (map #(json/read-str (slurp %) :key-fn keyword) fs as the map data,我试过修改你的代码稍微这样做,但我只是得到空列表。我认为需要另一个级别的迭代
    • @J.Greenfield 我使用您问题中的 JSON 编写了这个示例,这似乎只是您的一个文件,所以是的,我认为您只需要添加另一个级别的迭代。
    • 非常感谢,通过首先展平以避免嵌套迭代来设法使其工作,并将 get 中的字符串更改为 :keyword。
    猜你喜欢
    • 1970-01-01
    • 2018-12-15
    • 2022-01-18
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 2015-08-29
    • 2023-03-16
    相关资源
    最近更新 更多