[英]Clojure: Trying to convert a hash-map into a string
I am pretty new to Clojure and still trying to grasp the fundamentals.我是 Clojure 的新手,仍在努力掌握基础知识。 While experimenting, I had the following problem.
在试验时,我遇到了以下问题。 I tried to make a nested map and convert this into a JSON Object without the use of an external library, but keep running into a wall.
我试图在不使用外部库的情况下制作一个嵌套的 map 并将其转换为 JSON Object,但一直碰壁。 I was wondering if someone could guide / help me to get on the right track.
我想知道是否有人可以指导/帮助我走上正轨。
I want to thank you in advance for taking the time to read this and help me out.我想提前感谢您花时间阅读本文并帮助我。
I have the following hash-map in Clojure:我在 Clojure 中有以下哈希映射:
; Creating Hashmap
(def hashmap
[
{ :Mineral-1 {
:Mineral-name {:value "Gold"}
:Color {:value "Golden"}
:Weight {:value 2324.23}
:Count {:value 203}
:Price {:value 20320.49}
:DeliveryContainers {:value-1 {:value 1}
:value-2 {:value 2}
:value-3 {:value 3}}
:Sold {:value true}
}
}
{ :Mineral-2 {
:Mineral-name {:value "Silver"}
:Color {:value "Silvered"}
:Weight {:value 2313.23}
:Count {:value 425}
:Price {:value 12345.12}
:DeliveryContainers {:value-1 {:value 4}
:value-2 {:value 5}
:value-3 {:value 6}}
:Sold {:value false}
}
}
]
)
And I am trying to convert it to the following string:我正在尝试将其转换为以下字符串:
"
[{
"Minerals": [{
"Mineral-1": {
"Mineral-name": "Gold",
"Color": "Golden",
"Weight": 2324.23,
"Count": 203,
"Price": 20320.49,
"DeliveryContainers": [1, 2, 3]
},
"Mineral-2": {
"Mineral-name": "Silver",
"Color": "Silver",
"Weight": 2342.56,
"Count": 234,
"Price": 23123.23,
"DeliveryContainers": [4, 5, 6]
}
}]
}]"
Assuming you restrict yourself to a limited subset of Clojure structures, here is an example that you can use (if you excuse the poor formatting).假设您将自己限制在 Clojure 结构的有限子集中,这里有一个您可以使用的示例(如果您原谅糟糕的格式)。
user> (def hmap
[ { :Mineral-1 {
:Mineral-name {:value "Gold"}
:Color {:value "Golden"}
:Weight {:value 2324.23}
:Count {:value 203}
:Price {:value 20320.49}
:DeliveryContainers {:value-1 {:value 1}
:value-2 {:value 2}
:value-3 {:value 3}}
:Sold {:value true} } }
{ :Mineral-2 {
:Mineral-name {:value "Silver"}
:Color {:value "Silvered"}
:Weight {:value 2313.23}
:Count {:value 425}
:Price {:value 12345.12}
:DeliveryContainers {:value-1 {:value 4}
:value-2 {:value 5}
:value-3 {:value 6}}
:Sold {:value false} } } ])
#'user/hmap
user> (declare print-json) ; forward declaration
#'user/print-json
user> (defn print-json-map [x]
(print "{ ")
(run! (fn [[k v]]
(print (str "\"" (name k) "\""))
(print ": ")
(print-json v))
x)
(println "}"))
#'user/print-json-map
user> (defn print-json-vec [x]
(print "[ ")
(run! #(print-json %) x)
(println "]"))
#'user/print-json-vec
user> (defn print-json-prim [x]
(cond (string? x) (print (str "\"" x "\""))
(number? x) (print x)
(boolean? x) (print x)
:else (println "CANNOT HAPPEN")))
#'user/print-json-prim
user> (defn print-json [x]
(cond (map? x) (print-json-map x)
(vector? x) (print-json-vec x)
:else (print-json-prim x)))
#'user/print-json
user> (print-json hmap)
[ { "Mineral-1": { "Mineral-name": { "value": "Gold"}
"Color": { "value": "Golden"}
"Weight": { "value": 2324.23}
"Count": { "value": 203}
"Price": { "value": 20320.49}
"DeliveryContainers": { "value-1": { "value": 1}
"value-2": { "value": 2}
"value-3": { "value": 3}
}
"Sold": { "value": true}
}
}
{ "Mineral-2": { "Mineral-name": { "value": "Silver"}
"Color": { "value": "Silvered"}
"Weight": { "value": 2313.23}
"Count": { "value": 425}
"Price": { "value": 12345.12}
"DeliveryContainers": { "value-1": { "value": 4}
"value-2": { "value": 5}
"value-3": { "value": 6}
}
"Sold": { "value": false}
}
}
]
nil
user>
Since this is for educational purpose I made a solution using more of Clojure's build in language features:由于这是出于教育目的,我使用更多 Clojure 的内置语言功能制作了一个解决方案:
(import '[clojure.lang Sequential Keyword Symbol])
(import '[java.util Map])
(defprotocol MyJSON
(to-json [this]))
(def ^:dynamic *indent* 0)
(defmacro indent [& body]
`(binding [*indent* (inc *indent*)] ~@body))
(def indent-size 2)
(defn indent-space []
(apply str (repeat (* indent-size *indent*) " ")))
(defn comma-sep
([values] (comma-sep values ", "))
([values delim]
(apply str (butlast (interleave values (repeat delim))))))
(extend-protocol MyJSON
Boolean
(to-json [this] (str this))
String
(to-json [this] this)
Number
(to-json [this] (str this))
nil
(to-json [_] "null")
Keyword
(to-json [this] (name this))
Symbol
(to-json [this] (name this))
Sequential
(to-json [this] (str "[" (comma-sep (map to-json this)) "]"))
Map
(to-json [this] (str "\n" (indent-space) "{\n"
(indent (comma-sep
(map (fn [[k v]] (str (indent-space) (to-json k) ": " (to-json v))) this)
",\n"))
"\n"
(indent-space) "}" )))
Regarding {:value "1"}
, which transforms "1", to and {:value-1 "1":value-2 "2"}
, which transforms to ["1" "2"]
: I suggest to do this transformation first and finally convert the transformed data to json.关于
{:value "1"}
,它将 "1" 转换为和{:value-1 "1":value-2 "2"}
,它转换为["1" "2"]
:我建议这样做这个转换首先最后将转换后的数据转换为json。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.