     (.append sb \")
     (dotimes [i (count s)]
       (let [cp (int (.charAt s i))]
-        (cond
-         ;; Handle printable JSON escapes before ASCII
-         (= cp 34) (.append sb "\\\"")
-         (= cp 92) (.append sb "\\\\")
-         (= cp 47) (.append sb "\\/")
-         ;; Print simple ASCII characters
-         (< 31 cp 127) (.append sb (.charAt s i))
-         ;; Handle non-printable JSON escapes
-         (= cp 8) (.append sb "\\b")
-         (= cp 12) (.append sb "\\f")
-         (= cp 10) (.append sb "\\n")
-         (= cp 13) (.append sb "\\r")
-         (= cp 9) (.append sb "\\t")
-	 ;; Any other character is Unicode
-         :else (if escape-unicode?
-		 ;; Hexadecimal-escaped
-		 (.append sb (format "\\u%04x" cp))
-		 (.appendCodePoint sb cp)))))
+        (codepoint-case cp
+          ;; Handle printable JSON escapes before ASCII
+          \" (.append sb "\\\"")
+          \\ (.append sb "\\\\")
+          \/ (.append sb "\\/")
+          ;; Print simple ASCII characters
+          :simple-ascii (.append sb (.charAt s i))
+          ;; Handle JSON escapes
+          \backspace (.append sb "\\b")
+          \formfeed  (.append sb "\\f")
+          \newline   (.append sb "\\n")
+          \return    (.append sb "\\r")
+          \tab       (.append sb "\\t")
+          ;; Any other character is Unicode
+          (if escape-unicode?
+            ;; Hexadecimal-escaped
+            (.append sb (format "\\u%04x" cp))
+            (.appendCodePoint sb cp)))))
     (.append sb \")
     (.print out (str sb))))
 

  ;; Expects to be called with the head of the stream AFTER the
  ;; initial backslash.
  (let [c (.read stream)]
    (cond
     (#{(codepoint \") (codepoint \\) (codepoint \/)} c) (char c)
     (= c (codepoint \b)) \backspace
     (= c (codepoint \f)) \formfeed
     (= c (codepoint \n)) \newline
     (= c (codepoint \r)) \return
     (= c (codepoint \t)) \tab
     (= c (codepoint \u)) (read-json-hex-character stream))))

(defn- read-json-quoted-string [^PushbackReader stream]
  ;; Expects to be called with the head of the stream AFTER the


;;; JSON READER

(defmacro ^:private codepoint [c]
  (int c))

(declare read-json-reader)

(defn- codepoint-clause [[test result]]
  (cond (list? test)
          [(map int test) result]
        (= test :whitespace)
          ['(9 10 13 32) result]
        (= test :simple-ascii)
          [(remove #{(codepoint \") (codepoint \\) (codepoint \/)}
                   (range 32 127))
           result]
        :else
          [(int test) result]))

(defmacro ^:private codepoint-case [e & clauses]
   `(case ~e
      ~@(mapcat codepoint-clause (partition 2 clauses))
      ~@(when (odd? (count clauses))
          [(last clauses)])))

(defn- read-json-array [^PushbackReader stream keywordize?]
  ;; Expects to be called with the head of the stream AFTER the
  ;; opening bracket.
  (loop [c (.read stream), result (transient [])]
    (when (neg? c) (throw (EOFException. "JSON error (end-of-file inside array)")))
    (codepoint-case c
      :whitespace (recur (.read stream) result)
      \, (recur (.read stream) result)
      \] (persistent! result)
      (do (.unread stream c)
          (let [element (read-json-reader stream keywordize? true nil)]
            (recur (.read stream) (conj! result element)))))))

(defn- read-json-object [^PushbackReader stream keywordize?]
  ;; Expects to be called with the head of the stream AFTER the
  ;; opening bracket.
  (loop [c (.read stream), key nil, result (transient {})]
    (when (neg? c) (throw (EOFException. "JSON error (end-of-file inside array)")))
    (codepoint-case c
     :whitespace (recur (.read stream) key result)

     \, (recur (.read stream) nil result)

     \: (recur (.read stream) key result)

     \} (if (nil? key)
           (persistent! result)
           (throw (Exception. "JSON error (key missing value in object)")))

     (do (.unread stream c)
         (let [element (read-json-reader stream keywordize? true nil)]
           (if (nil? key)
             (if (string? element)
               (recur (.read stream) element result)
               (throw (Exception. "JSON error (non-string key in object)")))
             (recur (.read stream) nil
                    (assoc! result (if keywordize? (keyword key) key)
                            element))))))))

(defn- read-json-hex-character [^PushbackReader stream]
  ;; Expects to be called with the head of the stream AFTER the
