我正在研究Clojure API,但是当地图中的项目数发生变化时,遇到了关于Clojure在HashMap
和ArrayMap
之间自动“类型切换”的问题。
阅读文档:https://clojuredocs.org/clojure.core/array-map#example-57392e25e4b071da7d6cfd0c
假设我有这样的POST请求:
(POST "/" []
:body [foo FooSchema]
(create-response ok {:message "foo!"}))
FooSchema
定义如下:
(def ArrayMap clojure.lang.PersistentArrayMap)
(def Bar ArrayMap)
(s/defschema FooSchema
{:id s/Str
:bar Bar})
:bar
作为javascript对象发送,其结构如下:
{
id: 1,
fh: 1,
rdstr: "flying"
}
如文档中所述,如果:bar
对象在body
中返回少于9个项目,那么它将产生ArrayMap,它可以正常工作。无论如何,当:bar
对象缩放并返回超过9个项目时,请求失败,返回错误:
(not (instance? clojure.lang.PersistentArrayMap a-clojure.lang.PersistentHashMap))
因为:bar
已自动(神奇地)切换为HashMap
。
反之亦然,如果我将:bar
的架构类型设置为HashMap
,那么少于9个项目的对象也不起作用。
无论如何,我们总是可以将类型强制为HashMap
?
答案 0 :(得分:2)
这两种类型都太具体了。您应该使用更通用的类型,表示任何类似地图的类型。显而易见的选择是clojure.lang.IPersistentMap
。
答案 1 :(得分:0)
我假设您使用的是Plumatic Schema。
您可以定义一个谓词来捕获所有类型的地图,例如
(ns your.schema.namespace
(:require [schema.core :as s]))
(def Map (s/pred map?))
(defschema FooSchema
{:id s/Str
:bar Map})
map?
会在Clojure中为任何类型的地图返回true
=> (map? (array-map))
=> true
=> (map? (hash-map))
=> true