4

我正在向 JaxRs 注释服务添加 Swagger 注释。

我有以下内容:

(^{
 GET true
 Path "/{who}"
 ApiOperation {:value "Get a hello" :notes "simple clojure GET"}
 Produces ["text/plain; charset=UTF-8"]
 ApiResponses {:value [(ApiResponse {:code 200 :message "yay!"})]}

}

如果我反编译生成的类,注释如下所示:

@ApiResponses({@com.wordnik.swagger.annotations.ApiResponse(code=200L, message="yay!")})
@Produces({"text/plain; charset=UTF-8"})
@ApiOperation(value="Get a hello", notes="simple clojure GET")
@Path("/{who}")
@GET(true)

注意在第一个注释代码= 200L

在运行时,这个值必须是一个 int,我不知道如何做到这一点

如果我尝试

ApiResponses {:value [(ApiResponse {:code (int 200) :message "yay!"})]}

我收到编译错误(使用 maven swagger 插件)

Exception in thread "main" java.lang.ClassCastException: clojure.lang.Var cannot be cast to java.lang.Class, compiling:(pocclj/resourceclj.clj:14)

我努力了

(def success (int 200))
 ...
ApiResponses {:value [(ApiResponse {:code success :message "yay!"})]}

这会产生此编译错误:

Exception in thread "main" java.lang.IllegalArgumentException: Unsupported annotation value: success of class class java.lang.Integer, compiling:(pocclj/resourceclj.clj:14)

我尝试了很多其他的东西(deref 等),但找不到秘方。

我对clojure相当陌生,并且迫切需要一些帮助。

提前致谢

马丁

4

2 回答 2

0

您正在正确设置 ':code' 的类型。可以独立测试:

user> (def something ^{:ApiResponses {:code (int 200) :message "yay!"}} {:some :data :goes :here})
#'user/something

user> (meta something)
{:ApiResponses {:code 200, :message "yay!"}}

user> (-> (meta something) :ApiResponses :code type)
java.lang.Integer

如果没有演员表,元数据包含错误的类型:

user> (def something-wrong ^{:ApiResponses {:code 200 :message "yay!"}} {:some :data :goes :here})
#'user/something-wrong

user> (meta something)
{:ApiResponses {:code 200, :message "yay!"}}

user> (-> (meta something-wrong) :ApiResponses :code type)
java.lang.Long

从异常看来,对的调用可能ApiResponse正在崩溃。如果 ApiResponse 是一个需要数字而不是 s 表达式的宏,那么我可以看到它没有正确处理这个问题。如果它是一个函数,您需要查看它崩溃的原因。

如果我为 ApiResponse 提供存根实现,那么它对我有用:

user> (definterface Fooi (Something []))
user.Fooi

user> (def ApiResponse identity)
#'user/ApiResponse

user> (deftype Foo []
        Fooi
        (Something
          ^{GET true
            Path "/{who}"
            ApiOperation {:value "Get a hello" :notes "simple clojure GET"}
            Produces ["text/plain; charset=UTF-8"]
            ApiResponses {:value [(ApiResponse {:code (int 200) :message "yay!"})]}}
          [this] (identity this)))
user.Foo
于 2013-08-16T21:17:11.037 回答
0

我不太了解 ApiResponse,也不太了解注释,但是:看起来某个宏 ( deftype?) 正在为您生成注释,您需要将其200视为 int。Clojure 没有int文字,因此将 Integer 对象直接传递给宏的唯一方法是通过调用它的其他宏。真的不可能以一种好的方式做到这一点。eval据我所知,您必须通过专门针对 int 文字来使用或非常狭窄。这是一个解决方案的草图:

user> (use 'clojure.walk)
user> (defmacro with-int-literals [named-ints & body]
        (prewalk-replace (into {}
                               (for [[k v] (partition 2 named-ints)]
                                 [k (int v)]))
                         `(do ~@body)))

user> (map class (second (macroexpand-1 '(with-int-literals [x 100, y 200] [x y]))))
(java.lang.Integer java.lang.Integer)

因此,如果您将整个deftype(或生成这些注释的任何宏)包装在一个with-int-literals表单中,您可以为其生成整数而不是长整数。我实际上不知道这会起作用。也许注释处理器中的某些东西由于某种原因从根本上无法处理整数。但至少通过这种方式,您可以提供整数并希望获得最好的结果。

编辑

由于您实际上需要元数据中的 int 文字,而不是“普通”代码,prewalk因此实际上不会查看您关心的数据。您必须编写一个walk以合理方式处理元数据的版本,然后在此处使用它而不是 prewalk。

于 2013-08-18T07:11:54.063 回答