我的项目使用读/写库解析 JSON,称为:
柴郡核心
我遇到了问题,试图让解码(func(工作,所以我开始搞砸:
data.json
我的 JSON 包含由一个名为"zone"的字段组成的数据,其中包含一个内部带有 :keys 的向量,如下所示 {:zone : [:hand :table]} 存储在向量中的字符串中,如下所示: {"区域" : ["手" "表"]}
所以我想出了如何使用以下方法转换示例数据:
(mapv keyword {"zone" : ["hand"]})
这很棒,然后我需要弄清楚如何为 Cheshire 实现解码器,我无法用我的逻辑做到这一点,我只花了大约一个小时来解决这个问题,但我一直在使用 data.json,而且解码器功能相对容易我认为。
我让我的项目工作,这里有一些示例代码:
(ns clojure-noob.core (:require
[cheshire.core :refer [decode]]
[clojure.data.json :as j-data]
) (:gen-class))
(defn -main
"I don't do a whole lot ... yet."
[& args]
)
这是使用柴郡:
(let [init (decode "{"zone" : ["hand"]}" true
(fn [field-name]
(if (= field-name "zone")
(mapv keyword [])
[])))]
(println (str init)))
这是使用 data.json:
(defn my-value-reader [key value]
(if (= key :zone)
(mapv keyword value)
value))
(let [init (j-data/read-str
"{"zone" : ["hand"]}"
:value-fn my-value-reader
:key-fn keyword)]
(println (str init)))
我想要控制台中这两个的底部结果:
{:zone ["hand"]}
{:zone [:hand]}
问题是我想使用柴郡😎来做到这一点 附言我正在阅读柴郡的工厂部分?也许这更容易?
我同意@TaylorWood。不要弄乱解码器,只是一次咬一口。首先,解析 json。第二,转变结果。
(def data "{"zone" : ["hand"]}")
(-> data
(cheshire.core/decode true)
(update-in ["zone"] (partial mapv keyword)))
#=> {:zone [:hand]}
我建议你使用像schema.tools
这样的工具来强制输入。您可以添加第二个传递,尝试将 JSON 字符串强制转换为更丰富的 clojure 类型。
下面是一些示例代码!
;; require all the dependencies. See links below for libraries you need to add
(require '[cheshire.core :as json])
(require '[schema.core :as s])
(require '[schema.coerce :as sc])
(require '[schema-tools.core :as st])
;; your data (as before)
(def data "{"zone" : ["hand"]}")
;; a schema that wants an array of keywords
(s/defschema MyData {:zone [s/Keyword]})
;; use `select-schema` along with a JSON coercion matcher
(-> data
(json/decode true)
(st/select-schema MyData sc/json-coercion-matcher))
;; output: {:zone [:hand]}
使用defschema
来定义所需的数据形状,为您提供了序列化为 JSON 的通用解决方案,同时获得 Clojure 值类型的全部优势。您的架构不是显式地"执行"转换工作,而是描述预期的结果,希望强制可以做正确的事情!
图书馆链接: - https://github.com/plumatic/schema - https://github.com/metosin/schema-tools#coercion
注意:您可以使用metosin/spec-tools对clojure.spec做类似的事情。查看他们的自述文件以获取帮助。