Skip to content

Selecting Object literals

(obj) selects Object literals and, optionally, their properties -- similar to what (arr) does for Array literals. It has the following signature:

clojure
(obj [props?])

In its bare form, (obj) will match any Object, like {} or {a}:

clojure
(obj)

To select an object based on its properties, the (prop) selector can be used, which is also analogous to (el) for Array elements. It has the following signature:

clojure
(prop [key?] [val?])

The following query selects an object that has a property named by the identifier x:

clojure
(obj (prop x))

Property names are not restricted to identifiers: they can be strings -- { "a": 1 }, or numbers -- { 3: 1 }, or computed -- { [a]: 1 }. To be specific about the type of a key, we can use one of the corresponding selectors we've encountered before:

clojure
(obj (prop (str a))) ; { "a": 1 }
(obj (prop (comp (num)))) ; { [3]: 1 }

Property values can be selected in a similar fashion by providing a selector as the second argument to (prop):

clojure
(obj (prop x (str))) ; { x: "foo" }

When the property name is irrelevant, disregard it using the placeholder atom:

clojure
(obj (prop _ (str))) ; {   x: "foo" }
                     ; { [x]: "foo" }

Selecting objects based on multiple properties

As we've seen with Arrays in the introduction to the logical operators, we can use (:and) to combine multiple (prop) selectors and cover more than one property of an object. Say we want to select an object that has the properties named "headers" and "url":

clojure
(obj (:and (prop headers)
           (prop url)))

Alternating with (:or) and excluding with (:not) behave similarly. Alternates are especially useful for property selection since property names (keys) may be more than identifiers; a problem we did not have with Arrays. For example, to match the "headers" and "url" properties regardless of whether they are defined as an identifier or a string:

clojure
(obj (:and (prop (:or (id headers) (str "headers")))
           (prop (:or (id url)     (str "url")))))

Such patterns are often necessary and could get unwieldy rather quickly; consider that a name may also be a computed property of a string literal:

clojure
(obj (:and (prop (:or (id headers) (str "headers") (comp (str "headers"))))
           (prop (:or (id url)     (str "url")     (comp (str "url"))))))

SYNG provides dedicated constructs for dealing with these patterns. We discuss this in more detail later in the chapter on supertype selection.

Copyright © 2022-present Semantic Works, Inc.