3

I need to encode a Clojure byte array to JSON. I have been trying to do this using Cheshire's add-encoder function, like this:

(add-encoder [Ljava.lang.Byte encode-seq)

The problem is the reader always complains about an unmatched delimiter. I'm trying to encode something like the following:

{:bytes #<byte[] [B@9de27c>}

But this always gives me

JsonGenerationException Cannot JSON encode object of class: class [B: [B@9de27c cheshire.generate/generate (generate.clj:147)

So I'm trying to add a custom encoder. Am I even doing this the right way?

ChrisM
  • 2,128
  • 1
  • 23
  • 41

1 Answers1

4

While Clojure will resolve literal symbols containing . as the Java class named by the symbol, you can't specify array classes as Clojure literals because the reader interprets the [ as a token signifying the beginning of a vector. As suggested by this thread, the most concise way to get the byte-array class would be:

 (add-encoder (Class/forName "[B") encode-seq)
Alex
  • 13,811
  • 1
  • 37
  • 50
  • Well that did in fact work. Thank you. The only problem is the array might well be very large, and this method will produce a byte-for-byte representation. Is there any way to truncate it? – ChrisM Jun 10 '14 at 22:49
  • I'm sure there are lots of ways to shorten the byte array by encoding, compressing, or truncating it. Which one to use depends on how the JSON is going to be used - e.g. do you need to be able to reproduce the original byte array from the encoded form? But the issue of choosing an encoder is orthogonal to configuring Cheshire to use that encoder. – Alex Jun 10 '14 at 22:57
  • Well the actual bytes are not of any interest to me. So in the end I opted for: `(add-encoder (Class/forName "[B") (fn [c jg] (.writeString jg (format "#" c))))` – ChrisM Jun 11 '14 at 04:36