redplanetlabs / specter

Clojure(Script)'s missing piece
Apache License 2.0
2.51k stars 102 forks source link

Clarity on Navigator Composition? #284

Closed LusciousPear closed 4 years ago

LusciousPear commented 4 years ago

Coming back to Specter after a few years, and I'm trying to understand navigator composition.

The problem I'm trying to solve is "Transform these paths to JSON, and then if that item has these paths, transform that to JSON as well".

Using multi-path, I'm able to achieve this (elegantly!), the problem is that instead of ignoring non-existent paths, they are turned into nils. For example:

(def parse-paths
  "a list of paths to parse into JSON for the input. if any of these are found, it is parsed to metadata"
  [:payload
   [:payload :metadata]
   [:payload :Metadata]
   [:payload :CloudResource]
   [:payload :CloudResource :metadata]
   ])

using the fn (transform (apply multi-path parse-paths) parse-json raw-loe)

results in a structure like

 {:payload {:CloudResource {:metadata nil},
           :name "name",
           :customer "c",
           :Metadata nil} 

Wherein I don't want the values or parents of 'nil'.

I figured something like (comp must multi-path) would work, but that is incorrect.

Maybe a section on this with simple examples in the wiki would help? Unless I missed it somehow.

nathanmarz commented 4 years ago

You want to represent that first path as a vector and do this:

(apply multi-path (mapv #(apply must %) parse-paths))
LusciousPear commented 4 years ago

Ah, I see now. I apply it to each path, instead of the collection of paths. That makes a lot more sense.

Specter solves so many problems for me, this is great.