I'm trying to clean up some JSON data in Clojure. Some values in the JSON document are encapsulated in objects with associated (and no longer needed) metadata. I start with a JSON document like:
{ "household": {
"address": {
"street": { "value": "123 Fire Ln", "foo": "bar1" },
"zip": { "value": "01234", "foo": "bar2" }
},
"persons": [
{
"id": "0001",
"name": { "value": "John Smith", "foo": "bar3" }
},
{
"id": "0002",
"name": { "value": "Jane Smith", "foo": "bar4" }
}
]
} }
Using Cheshire I parse this JSON and get the following data structure:
{ "household" {
"address" {
"street" {"value" "123 Fire Ln", "foo" "bar1"},
"zip" {"value" "01234", "foo" "bar2"}
},
"persons" [
{"id" "0001", "name" {"value" "John Smith", "foo" "bar3"}}
{"id" "0002", "name" {"value" "Jane Smith", "foo" "bar4"}}
]
} }
My goal is to "collapse" those nested maps with a "value" key, drop the "foo" assoc, and assign the value to the map key one level higher (e.g., "street", "zip", "name"). The resulting data structure would look like:
{ "household" {
"address" {
"street" "123 Fire Ln",
"zip" "01234"
},
"persons" [
{"id" "0001", "name" "John Smith"}
{"id" "0002", "name" "Jane Smith"}
]
} }
Any help here would be wonderful, thanks!
Sounds like a job for clojure.walk/postwalk
!
(defn collapse [obj]
(postwalk (fn [obj]
(or (and (map? obj)
(get obj "value"))
obj))
obj))
You can actually shorten this substantially because get
is willing to work on non-map objects (it just returns nil
), but I think it's a lot more clear what is going on in the first version.
(defn collapse [obj]
(postwalk #(get % "value" %) obj))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With