2012-03-08 44 views
4

我正试图清理Clojure中的一些JSON数据。 JSON文档中的一些值封装在具有关联(且不再需要)元数据的对象中。我开始像一个JSON文件:Clojure:如何使用特定键折叠嵌套地图?

{ "household": { 
    "address": { 
     "street": { "value": "123 Fire Ln", "foo": "bar1" }, 
     "zip": { "value": "", "foo": "bar2" } 
    }, 
    "persons": [ 
     { 
      "id": "0001", 
      "name": { "value": "John Smith", "foo": "bar3" } 
     }, 
     { 
      "id": "0002", 
      "name": { "value": "Jane Smith", "foo": "bar4" } 
     } 
    ] 
} } 

使用柴我解析此JSON,并得到如下数据结构:

{ "household" { 
    "address" { 
     "street" {"value" "123 Fire Ln", "foo" "bar1"}, 
     "zip" {"value" "", "foo" "bar2"} 
    }, 
    "persons" [ 
     {"id" "0001", "name" {"value" "John Smith", "foo" "bar3"}} 
     {"id" "0002", "name" {"value" "Jane Smith", "foo" "bar4"}} 
    ] 
} } 

我的目标是“崩溃”的嵌套地图与“值”键,放下“foo”assoc,然后将值分配给高一级的地图键(例如,“street”,“zip”,“name”)。由此产生的数据结构将如下所示:

{ "household" { 
    "address" { 
     "street" "123 Fire Ln", 
     "zip" "" 
    }, 
    "persons" [ 
     {"id" "0001", "name" "John Smith"} 
     {"id" "0002", "name" "Jane Smith"} 
    ] 
} } 

这里的任何帮助将是美好的,谢谢!

回答

8

听起来像是clojure.walk/postwalk的工作!

(defn collapse [obj] 
    (postwalk (fn [obj] 
       (or (and (map? obj) 
         (get obj "value")) 
        obj)) 
      obj)) 

实际上,你可以缩短这实质上是因为get愿意在非映射对象工作(它只是返回nil),但我认为这是一个很多更清楚什么是在第一个版本回事。

(defn collapse [obj] 
    (postwalk #(get % "value" %) obj))