JSON Versus S-Expressions (Again)

I’ve written several posts concerning the relative merits of JSON vs S-expressions (1, 2, 3, 4) and concluded that while s-expressions are more powerful and flexible, JSON might be a better choice because it’s supported by virtually all programming languages. A couple of days ago, Eli Bendersky published a post that reached similar conclusions. While his conclusions pretty much align with mine his reasoning does not and I disagree with it.

Bendersky approaches the question from the standpoint of parsimony and says that while JSON is a win over XML because it’s more “fat free,” you can’t go further and replace JSON with sexprs to get rid of even more fat because there’s no easy way to handle dictionary structures. He says that the equivalent S-expression to the JSON expression

'[["oranges", 2], ["apples", 6], ["pears" 5]]'

is

'((ORANGES 2) (APPLES 6) (PEARS 5))

which is indeed less punctuation but that as soon as you have the JSON expression

'{"oranges": 2, "apples": 6, "pears": 5}'

S-expressions lose because there’s no way to express a dictionary structure with sexprs without adding abstraction.

That’s certainly not true. Here, for example, is a Common Lisp reader macro that does just that.

(defun |#H-reader| (stream sub-char numarg)
  (declare (ignore sub-char numarg))
  (let* ((kv (read stream t nil t))
         (h (make-hash-table :test 'equal :size (* 2 (length kv)))))
    (mapc (lambda (p)
            (destructuring-bind (key value) p
              (setf (gethash (symbol-name key) h) value)))
          kv)
    h))

(set-dispatch-macro-character #\# #\H #'|#H-reader|)

Notice how short and easy it is to write. Now we can treat that sexpr as a dictionary simply by prepending #H.

CL-USER> (setq dict #H((oranges 2) (apples 6) (pears 5)))
#<HASH-TABLE :TEST EQUAL size 3/31 #x3020009740CD>
CL-USER> (gethash "APPLES" dict)
6
T

Or we can prepend ' and treat it as an association list or simply an unordered list.

“But I don’t use Lisp” I hear you say. I could respond that your choice to use a less powerful language is not my problem but I won’t do that precisely because that’s the reason JSON may make more sense: it’s supported in all programming languages.

Bendersky remarks that he can read

'{"oranges": 2, "apples": 6, "pears": 5}'

directly into Python or Javascript and get his dictionary-like structure. As I showed above, you can do that in Lisp too. Now what about all those other languages? How is JSON more natural and direct in, say, C++ than an S-expression? Sure, there are JSON libraries for them but that’s adding abstraction and if we can do it for JSON we can also do it for S-expressions.

I believe JSON may be a better solution because it represents a sort of lowest acceptable common denominator. It’s simple, everyone understands it, and there are libraries for every imaginable language. But that doesn’t mean it’s better in some absolute or esthetic sense. It isn’t. S-expressions are more powerful (because of the duality of code and data), more flexible, and have less syntactic sugar.

In any event, Bendersky’s post is interesting and makes some good points. You should really take a look and decide whether you agree with him or not.

Update: mapcar → mapc. The mapcar works, of course, but there’s no reason to build the list of values and then throw it away.

Update 2: associative array → association list

This entry was posted in General and tagged , . Bookmark the permalink.