使用 Cheshire 解析为 json - generate- string 和 parse-string

Parsing to json with Cheshire - generate- string and parse-string

我正在尝试导出 json-schema 以便在 javascript 中的 Clojure 之外使用。我能够生成这个:

{:type "object",
 :properties {:$class {:type "string"},
              :name {:type "string"},
              :clauseId {:type "string"},
              :$identifier {:type "string"}},
 :required [:$class :name :clauseId :$identifier]}

这对 Clojure 来说很好

Cheshire 使用 generate-string 我可以得到:

"{
   \"type\" : \"object\",
   \"properties\" : {
     \"$class\" : {
       \"type\" : \"string\"
     },
     \"name\" : {
       \"type\" : \"string\"
     },
     \"clauseId\" : {
       \"type\" : \"string\"
     },
     \"$identifier\" : {
       \"type\" : \"string\"
     }
   },
   \"required\" : [ \"$class\", \"name\", \"clauseId\", \"$identifier\" ]
 }"

这基本上是我想要的,但没有引号。我在上面尝试了来自 Cheshire 的 parse-string,我得到:

{"type" "object",
 "properties" {"$class" {"type" "string"},
               "name" {"type" "string"},
               "clauseId" {"type" "string"},
               "$identifier" {"type" "string"}},
 "required" ["$class" "name" "clauseId" "$identifier"]}

更接近了,但是去掉了冒号。我要

{"type" : "object",
 "properties" : {"$class" : {"type" "string"},
               "name" : {"type" "string"},
               "clauseId" : {"type" "string"},
               "$identifier" : {"type" "string"}},
 "required" : ["$class" "name" "clauseId" "$identifier"]}

我觉得这应该很容易,但我遗漏了一些东西。如果没有 :

,我看不出它是如何有效的 json

如何创建带冒号的 json?

我认为打印命令是这里混乱的根源。你没有在你的问题中表明这一点。

另一个混淆点是将 JSON 打印为“源”或“数据”。在后者中,JSON 字符串必须转义双引号。在 JS 源代码中,这些是不存在的。

一个例子:

(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:require [tupelo.string :as str]))

(dotest
  (let [edn-data {:a 1 :b [2 "three"]}
        json-str (edn->json edn-data)]

    (println :a edn-data) ; prints w/o double-quotes
    (prn     :b edn-data) ; prints with double-quotes, as if source code

    (newline)
    (println :c json-str)
    (prn     :d json-str)

结果

-----------------------------------
   Clojure 1.10.3    Java 15.0.2
-----------------------------------

Testing tst.demo.core
:a {:a 1, :b [2 three]}
:b {:a 1, :b [2 "three"]}

:c {"a":1,"b":[2,"three"]}
:d "{\"a\":1,\"b\":[2,\"three\"]}"

函数edn->json来自Tupelo library, but is similar to the Cheshire lib

另请参阅 this list of Clojure documentation 来源,尤其是。 Clojure 备忘单。


如果我们继续,我们可以看到一些处理 JSON 数据的好技巧:

    (let [json-single  (str/quotes->single json-str)
          json-literal "{'a':1,'b':[2,'three']}"
          json-double  (str/quotes->double json-literal)
          edn-data2    (json->edn json-double)]
      (is= json-single json-literal)
      (is= json-double json-str)
      (is= edn-data edn-data2))
    ))

Clojure 源代码中有 JSON 个字符串的根本问题是它是一个字符串,需要双引号才能写成字符串文字。这意味着需要转义内部双引号,这很丑陋且容易出错。

我们可以避免这个问题,我们只需使用单引号将 JSON "literal" 写成,如变量 json-literal 所示。然后我们可以使用函数 tupelo.string/quotes->double 将字符串中的单引号转换为双引号。

单元测试表明这与原始 JSON 等效。此外,由于单元测试回避了 printlnprn 的问题,因此不会因终端上的显示格式而造成混淆。


哦对了,

以上是在my favorite template project.

中完成的

正如 Alan Thompson 提到的,如果我们可以假设反斜杠是 REPL 显示数据的方式的产物,JSON 看起来引用得当。

Cheshire 的 README https://github.com/dakrone/cheshire 给出了一个解析 JSON 并将键作为关键字返回的示例。显然,您直接在 JSON 参数之后添加了一个布尔参数 true。