           (if-not (= value-fn out-value)
             (do
               (when have-printed-kv
-                (.print out \,))
+                (.append out \,))
               (write-string out-key out options)
-              (.print out \:)
+              (.append out \:)
               (-write out-value out options)
               (when (seq nxt)
                 (recur nxt true)))
             (when (seq nxt)
               (recur nxt have-printed-kv)))))))
-  (.print out \}))
-
-(defn- write-array [s ^PrintWriter out options]
-  (.print out \[)
+  (.append out \}))
+
+(defn- write-array [s ^Appendable out options]
+  (.append out \[)
   (loop [x s]
     (when (seq x)
       (let [fst (first x)
             nxt (next x)]
         (-write fst out options)
         (when (seq nxt)
-          (.print out \,)
+          (.append out \,)
           (recur nxt)))))
-  (.print out \]))
-
-(defn- write-bignum [x ^PrintWriter out options]
-  (.print out (str x)))
-
-(defn- write-float [^Float x ^PrintWriter out options]
+  (.append out \]))
+
+(defn- write-bignum [x ^Appendable out options]
+  (.append out (str x)))
+
+(defn- write-float [^Float x ^Appendable out options]
   (cond (.isInfinite x)
         (throw (Exception. "JSON error: cannot write infinite Float"))
         (.isNaN x)
         (throw (Exception. "JSON error: cannot write Float NaN"))
         :else
-        (.print out x)))
-
-(defn- write-double [^Double x ^PrintWriter out options]
+        (.append out (str x))))
+
+(defn- write-double [^Double x ^Appendable out options]
   (cond (.isInfinite x)
         (throw (Exception. "JSON error: cannot write infinite Double"))
         (.isNaN x)
         (throw (Exception. "JSON error: cannot write Double NaN"))
         :else
-        (.print out x)))
-
-(defn- write-plain [x ^PrintWriter out options]
-  (.print out x))
-
-(defn- write-null [x ^PrintWriter out options]
-  (.print out "null"))
+        (.append out (str x))))
+
+(defn- write-plain [x ^Appendable out options]
+  (.append out (str x)))
+
+(defn- write-null [x ^Appendable out options]
+  (.append out "null"))
 
 (defn- write-named [x out options]
   (write-string (name x) out options))

        returns itself, the key-value pair will be omitted from the
        output. This option does not apply to non-map collections."
  [x ^Writer writer & options]
  (-write x (PrintWriter. writer) (merge default-write-options (apply array-map options))))

(defn write-str
  "Converts x to a JSON-formatted string. Options are the same as
  write."
  [x & options]
  (let [sw (StringWriter.)]
    (-write x (PrintWriter. sw) (merge default-write-options (apply array-map options)))
    (.toString sw)))

;;; JSON PRETTY-PRINTER


(defprotocol JSONWriter
  (-write [object out options]
    "Print object to Appendable out as JSON"))

(defn- ->hex-string [^Appendable out cp]
  (let [cpl (long cp)]
    (.append out "\\u")
    (cond
      (< cpl 16)
      (.append out "000")
      (< cpl 256)
      (.append out "00")
      (< cpl 4096)
      (.append out "0"))
    (.append out (Integer/toHexString cp))))

(def ^{:tag "[S"} codepoint-decoder
  (let [shorts (short-array 128)]
