clojureclojure-java-interopedncheshire

How to convert Java String to EDN object?


In Clojure, I am using 'generate-string' function of cheshire (https://github.com/dakrone/cheshire) library to convert EDN to JSON.

It works fine if I call it directly using EDN data in Clojure i.e.

(defn generate-json-string
  (generate-string {:foo "bar" :baz {:eggplant [1 2 3]} :sesion nil} {:pretty true})
)

Output =>
{
  "foo": "bar",
  "baz": {
    "eggplant": [1,2,3]
  },
  "sesion": null
}

But it wont work if I call above function from Java and pass above same content in the form of Java String to it

(defn generate-json-string [content]
  (generate-string content {:pretty true})
)

Output => 
"{:foo \"bar\" :baz {:eggplant [1 2 3]} :session nil}"

How can I fix this?


Solution

  • The following shows how to read/write data into either a JSON string or an EDN string.

    Note that both JSON & EDN are string serialization formats, although Clojure literal data structures are often (sloppily) referred to as "EDN data" of just "EDN", even though EDN technically means the string representation.

    Also, note that clojure.tools.reader.edn is the best (safest) way to convert an EDN string into a Clojure data structure.

    (ns tst.demo.core
      (:use tupelo.core tupelo.test)
      (:require
        [clojure.tools.reader.edn :as edn]
        [tupelo.core :as t]
        [tupelo.string :as ts] ))
    
    (def data
      "A clojure data literal"
      {:a "hello" :b {:c [1 2 3]}})
    
    (dotest
      (let [json-str  (t/edn->json data) ; shortcut to Cheshire
            from-json (t/json->edn json-str) ; shortcut to Cheshire
    
            edn-str   (pr-str data) ; convert Clojure data structure => EDN string
            ; Using clojure.tools.reader.edn is the newest & safest way to
            ; read in an EDN string => data structure
            from-edn  (edn/read-string edn-str)]
    
        ; Convert all double-quotes to single-quotes for ease of comparison
        ; with string literal (no escapes needed)
        (is= (ts/quotes->single json-str) "{'a':'hello','b':{'c':[1,2,3]}}")
        (is= (ts/quotes->single edn-str)  "{:a 'hello', :b {:c [1 2 3]}}")
    
        ; If we don't convert to single quotes, we get a messier escaped
        ; string literals with escape chars '\'
        (is-nonblank= json-str "{\"a\":\"hello\",\"b\":{\"c\":[1,2,3]}}")
        (is-nonblank= edn-str   "{:a   \"hello\", :b   {:c    [1 2 3]}}")
    
        ; Converting either EDN or JSON string into clojure data yields the same result
        (is= data
          from-json
          from-edn)))