要するにEntityを元にJsonSchemaを生成するConverterがあるってことですね。
普通にJsonSchemaを出力してみると
class Text { @Column var title: String = "" @Column var page: Int = 0 @Column @Enumerated(EnumType.STRING) var category: CategoryType = CategoryType.Memo enum class CategoryType { Memo, Article, Log, Code } }
上のEntityがあったとして、
RequestHeader -> Accept: application/schema+json HttpRequest.GET -> /profile/texts
となげると
{ title: "Text", type: "object", properties: { title: { title: "Title", type: "string" }, page: { title: "Page", type: "integer" }, category: { title: "Category", type: "string", enum: [ "Memo", "Article", "Log", "Code" ] } } }
といったものが返ってきます。(一部不要な部分は削ってます)
このEntityの一部にJsonIgnoreを指定してみます
class Text { @Column var title: String = "" @JsonIgnore @Column var page: Int = 0 @Column @Enumerated(EnumType.STRING) var category: CategoryType = CategoryType.Memo enum class CategoryType { Memo, Article, @JsonIgnore Log, @JsonIgnore Code } }
同じリクエストをなげた場合、返ってくるのは、
{ title: "Text", type: "object", properties: { title: { title: "Title", type: "string" }, category: { title: "Category", type: "string", enum: [ "Memo", "Article", "Log", "Code" ] } } }
となります。
pageプロパティは期待どおり出力されなくなりましたが、categoryプロパティのenum値は全て出力されてしまっています。
これをどうにかしたいのが、本題。
enum値のJsonSchemaはJsonSchema.EnumPropertyというクラスで実装されています。
標準のconverter相当の作り方をした場合
fun buildSchema(clazz: Class<Any>): JsonSchema.JsonSchemaProperty? { return when { clazz.isEnum -> buildEnumSchema(clazz) else -> null } } fun buildEnumSchema(clazz: Class<Any>): JsonSchema.JsonSchemaProperty { return JsonSchema.EnumProperty("name", "title", clazz, "description", false) }
少し雑ですが、要するに、Classを渡して生成しています。
Classを渡した場合のコンストラクタは、
* 全Enumメンバーを取得
* toStringしてList化
* 別のコンストラクタへ渡す
という処理になっているので、JsonIgnore分を削ったListを用意して、その「別のコンストラクタ」をダイレクトに呼んであげれば良さそうです。
JsonIgnoreなメンバを省いたEnumPropertyを作る場合
上の処理を書き換えます。
fun buildEnumSchema(clazz: Class<Any>): JsonSchema.JsonSchemaProperty { clazz as Class<Enum<*>> return JsonSchema.EnumProperty("name", "title", clazz.enumConstants.filter { clazz.fields[it.ordinal] .getAnnotationsByType(JsonIgnore::class.java) .isEmpty() }.map { it.toString() }.toList(), "description", false) }
これをConverterに組み込んで、JsonSchema取得のリクエストをなげてみると、
{ title: "Text", type: "object", properties: { title: { title: "Title", type: "string" }, category: { title: "Category", type: "string", enum: [ "Memo", "Article" ] } } }
categoryのenumの値もフィルタリングされました。
やっていることは単純で、enumメンバのうち、JsonIgnoreが貼られているものを除外してtoStringしたものを渡してEnumPropertyを作っているだけです。
ポイントは、ClassがEnumだと後続処理に教える為に未代入でキャストしているのと、enumConstantsを再度、自身のClassからFieldとして取得してAnnotationを見れるようにするところでしょうか。
最新のSDRならもしかしたら、わざわざやらなくてもいけるのかな?とか思いますが、まあ、メモ程度ってことで。
いじょ