Clojure:定义模式中的哈希映射和数组映射类型冲突

Clojure: hash-map and array-map type conflicts in defined schema

我正在研究 Clojure API,但 运行 关于 Clojure 在 HashMapArrayMap 之间自动 "type-switching" 的问题里面的地图变化。

阅读文档: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"
}

如文档中所述,如果 body 中的 :bar 对象 return 少于 9 个项目,那么它会生成 ArrayMap,它工作正常。 Anyway,当:bar对象缩放和return超过9项时,请求失败,return错误:

(not (instance? clojure.lang.PersistentArrayMap a-clojure.lang.PersistentHashMap))

因为 :bar 自动(神奇地)切换为 HashMap

反之亦然,如果我将 :bar 的架构类型设置为 HashMap,则少于 9 个项目的对象也不起作用。

无论如何我们总是可以强制类型为 HashMap?

两种类型都太具体了。您应该使用更通用的类型,代表任何类似地图的东西。显而易见的选择是 clojure.lang.IPersistentMap.

我假设您正在使用 Plumatic Schema

您可以像这样定义一个谓词来捕获所有类型的地图

(ns your.schema.namespace
  (:require [schema.core :as s]))

(def Map (s/pred map?))

(defschema FooSchema
  {:id s/Str
   :bar Map})

map? returns true 对于 Clojure 中的任何类型的映射

=> (map? (array-map))
=> true
=> (map? (hash-map))
=> true