0

我正在尝试导出 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 来说很好

使用使用生成字符串的柴郡,我可以得到:

"{
   \"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?

4

2 回答 2

1

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

另一个混淆点是将 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 库,但类似于Cheshire lib等。

另请参阅此 Clojure 文档源列表,尤其是。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“文字”,如变量json-literal. 然后我们可以使用该函数tupelo.string/quotes->double将字符串中的单引号转换为双引号。

单元测试显示了它与原始 JSON 的等效性。此外,由于单元测试回避了printlnvs的问题prn,因此不会因终端上的显示格式而产生混淆。


哦耶,

以上是在我最喜欢的模板项目中完成的。

于 2021-07-06T04:34:58.883 回答
0

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

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

于 2021-07-06T09:36:20.063 回答