2

我已经为自定义标签定义了 EDN 阅读器,它在出现自定义标签时创建新对象。我正在使用 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]"]}

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

4

1 回答 1

3

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

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

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

现在,最好提供一种逻辑用于以人类可读的方式进行打印,并提供一种用于以可以回读的方式进行打印的逻辑。因此,print它将以人类可读pr的方式打印,并且将以您可以使用自定义阅读器回读的方式打印。

(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}"
于 2019-11-29T06:57:07.577 回答