如何避免在使用 clojure 将 EDN 文件读入 java 对象时打印对象哈希码

How can I avoid printing object hashcode while reading EDN file in to java objects using clojure

我已经为自定义标签定义了 EDN reader,它在出现自定义标签时创建新对象。 我正在使用 edn/read-string 读取 EDN 数据。

(defn getXyz [str]
    (.getXyz (XyzBuilder.) str)
)

(defn custom-readers []
    {'xyz/builder getXyz}
)

(defn getSomeObj
    [filename myEdnFile]
    (edn/read-string
        {:readers custom-readers}
        (slurp myEdnFile))
)

我的 EDN 文件

{
   "version" "1.0"
   "xyz" #xyz/builder "testString"
}

当我从 java 打印 getSomeObj 的输出时,它会打印以下输出

{"version" "1.0", "Xyz" #object[com.java.sample.Xyz 0x6731787b "Xyz [type=type_1]"]}

我想避免在 return 字符串中获取对象哈希码(即#object[com.java.sample.Xyz 0x6731787b)。有办法实现吗?

是的,您需要为其定义打印方法的自定义实现:

(defmethod print-method Xyz [obj writer]
  (.write writer (.getXyz obj)))

您应该将 (.getXyz obj) 替换为您想要打印内容的任何逻辑。

现在,最好提供一种以人类可读方式打印的逻辑,以及一种以可读回方式打印的逻辑。这样 print 将以人类可读的方式打印,而 pr 将以您可以使用自定义 reader.

阅读的方式打印
(defmethod print-method Xyz [obj writer]
  (if *print-readably*
    (.write writer (str "#xyz/builder " "\"" (.getXyz obj) "\""))
    (.write writer (.getXyz obj))))

*print-readably* 为真时,您希望以机器可读的方式打印,以便 edn/read-string 可以再次读回。

这是一个完整的示例,我使用 StringBuilder 而不是 Xyz,因为它很方便并且默认情况下它打印为对象内存位置(你说的看起来像散列)就像你问的那样。

(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}"