Improved JavaScript Object Literal Printing

July 29, 2017

A change landed in the ClojureScript 1.9.854 release which improves JavaScript object literal printing, using string keys when property names cannot be represented as keywords.




ClojureScript supports #js for object and array literals. For example, the JavaScript object

{ foo: 1, bar: "a" }

can be represented in ClojureScript as

#js {:foo 1, :bar "a"}

where the property names are represented as keywords.

But, in ClojureScript 1.9.671 and earlier, this fails when property names are blindly converted to keywords during printing. Take, for example, the case when a property name has a space in it:

{ "alpha beta": 2 }

Well, since (keyword "alpha beta") yields :alpha beta, this prints as

#js {:alpha beta 2}

which, of course, can't be round-tripped if you try to read that back in. Things can also derail if property names have slashes in them, with

{ "gamma/delta": 3 }

causing an exception if *print-namespace-maps* is set to true.

ClojureScript 1.9.854, on the other hand, takes the approach where property names are only represented as keywords if they can be converted to legal unqualified keywords, otherwise string notation is used. The above examples print as

#js {"alpha beta" 2}

and

#js {"delta/gamma" 3}

Note that string and keyword notation can be intermixed, as in

#js {:foo 1, :bar "a", "alpha beta" 2, "delta/gamma" 3}

ClojureScript 1.9.854 only fixes the printing for JavaScript object literals; reading of forms like the above worked just fine in previous versions of ClojureScript.

Tags: ClojureScript