I have defined EDN reader for custom tags which creates new object on occurrence of custom tags. I am making use of edn/read-string to read EDN data.
(defn getXyz [str]
(.getXyz (XyzBuilder.) str)
)
(defn custom-readers []
{'xyz/builder getXyz}
)
(defn getSomeObj
[filename myEdnFile]
(edn/read-string
{:readers custom-readers}
(slurp myEdnFile))
)
My EDN file
{
"version" "1.0"
"xyz" #xyz/builder "testString"
}
When I print output of getSomeObj from java, it prints following output
{"version" "1.0", "Xyz" #object[com.java.sample.Xyz 0x6731787b "Xyz [type=type_1]"]}
I want to avoid getting object hashcode (i.e. #object[com.java.sample.Xyz 0x6731787b) in the return string.. Is there a way to achieve it?
Yes, you need to define a custom implementation of print-method for it:
(defmethod print-method Xyz [obj writer]
(.write writer (.getXyz obj)))
You should replace (.getXyz obj)
with whatever logic you want for what gets printed.
Now, it is best if you provide one logic for printing in a human readable way, and one for printing in a way that can be read back. So that print
will print in a human readable way, and pr
will print in a way you can read back with your custom reader.
(defmethod print-method Xyz [obj writer]
(if *print-readably*
(.write writer (str "#xyz/builder " "\"" (.getXyz obj) "\""))
(.write writer (.getXyz obj))))
When *print-readably*
is true, you want to print in a machine readable way, so a way that edn/read-string
can read it back again.
Here's a full example, I used StringBuilder instead of Xyz, sinc it was convenient and by default it prints as the object memory location (what you said looked like a hash) just like what you were asking.
(defn getXyz [str]
(StringBuilder. str))
(defn custom-readers []
{'xyz/builder getXyz})
(defn getSomeObj
[]
(edn/read-string
{:readers (custom-readers)}
"{\"version\" \"1.0\"
\"xyz\" #xyz/builder \"testString\"}"))
(defmethod print-method StringBuilder [obj writer]
(if *print-readably*
(.write writer (str "#xyz/builder " "\"" (.toString obj) "\""))
(.write writer (str "The xyz is: " (.toString obj)))))
(getSomeObj)
;; => {"version" "1.0", "xyz" #xyz/builder "testString"}
(pr-str (getSomeObj))
;; => "{\"version\" \"1.0\", \"xyz\" #xyz/builder \"testString\"}"
(print-str (getSomeObj))
;; => "{version 1.0, xyz The xyz is: testString}"