如何正确覆盖 JacksonAnnotationIntrospector._findAnnotation 以替换元素的注释 [英] How to properly override JacksonAnnotationIntrospector._findAnnotation to replace an annotation of the element
问题描述
我正在尝试创建一些可由 Jackson 序列化的类.我想用标准的 Jackson 注释来注释一些元素(在这个例子中让我们考虑 JsonIgnore
),但我希望它们只在我的特定映射器中有效.
I am trying to create some classes serializable by Jackson. I want to annotate some elements with standard Jackson annotation (let's consider JsonIgnore
for this example) but I want them to have effect only in my specific mapper.
所以我决定像标准的一样创建我自己的注释(例如 MyJsonIgnore),并且只在我的映射器使用的注释内省器中处理它们.我发现了可覆盖的方法 _findAnnotation
.Javadoc 说明如下:
So I decided to create my own annotations like standard ones (e. g. MyJsonIgnore) and process them only in an annotation introspector used by my mapper. I've found overridable method _findAnnotation
. Javadoc says the following:
...overridable that sub-classes may, if they choose to,
mangle actual access block access ("hide" annotations)
or perhaps change it.
我找到了一种阻止某些注释的方法(但它涉及覆盖 _hasAnnotation
,而不是 _findAnnotation
),但我完全坚持更改注释.
I've found a way to block some annotations (however it involves overriding _hasAnnotation
, not _findAnnotation
) but I am completely stuck with changing annotations.
这是我正在尝试做的一些最小的例子:
Here is some minimal example of what I am trying to do:
object Mappers {
/**
* Same as JsonIgnore but mapper-specific
*/
annotation class MyJsonIgnore(val value: Boolean = true)
private class MyIntrospector : JacksonAnnotationIntrospector() {
override fun <A : Annotation> _findAnnotation(
annotated: Annotated,
annoClass: Class<A>
): A {
if (annoClass == JsonIgnore::class.java && _hasAnnotation(annotated, MyJsonIgnore::class.java)) {
val mji = _findAnnotation(annotated, MyJsonIgnore::class.java)
return JsonIgnore(mji.value) // Does not compile, type mismatch
// return JsonIgnore(mji.value) as A // Does not compile, annotation class cannot be instantiated, same as Java, see below
}
return super._findAnnotation(annotated, annoClass)
}
}
fun myMapper(): ObjectMapper {
return ObjectMapper().setAnnotationIntrospector(MyIntrospector())
}
}
我也不能用 Java 来做:
I also cannot do it with Java:
public class Mappers {
/**
* Same as JsonIgnore but mapper-specific
*/
public @interface MyJsonIgnore {
boolean value() default true;
}
private static class MyIntrospector extends JacksonAnnotationIntrospector {
@Override
protected <A extends Annotation> A _findAnnotation(Annotated annotated,
Class<A> annoClass) {
if (annoClass == JsonIgnore.class && _hasAnnotation(annotated, MyJsonIgnore.class)) {
MyJsonIgnore mji = _findAnnotation(annotated, MyJsonIgnore.class);
return new JsonIgnore(mji.value()); // Does not compile, JsonIgnore is abstract
}
return super._findAnnotation(annotated, annoClass);
}
}
static ObjectMapper myMapper() {
return new ObjectMapper().setAnnotationIntrospector(new MyIntrospector())
}
}
那么通过覆盖此方法来更改注释的假设方法是什么?有没有?我的方法是对的还是应该以其他方式做?
So what is the supposed way to change annotations by overriding this method? Is there any? Is my approach right or should I do it other way?
推荐答案
这里的主要问题是不能实例化注解类.不过有一个解决方案:您可以存储 一个注释作为另一个注释的成员 像这样:
The main problem here is that you can't instantiate the annotation class. There is one solution though: you could store one annotation as a member of another annotation like this:
@Retention(AnnotationRetention.RUNTIME) // don't forget
@Target(AnnotationTarget.FIELD) // these annotations
annotation class MyJsonIgnore(val value: Boolean = true, val jsonIgnore: JsonIgnore = JsonIgnore())
所以 MyJsonIgnore
里面会有一个实例化的 JsonIgnore
.然后你可以在你的 AnnotationIntrospector
中使用它:
So MyJsonIgnore
will have an instantiated JsonIgnore
inside. And then you can use it in your AnnotationIntrospector
:
private class MyIntrospector : JacksonAnnotationIntrospector() {
override fun <A : Annotation> _findAnnotation(
annotated: Annotated,
annoClass: Class<A>
): A? {
if (annoClass == JsonIgnore::class.java && _hasAnnotation(annotated, MyJsonIgnore::class.java)) {
val mji = _findAnnotation(annotated, MyJsonIgnore::class.java)
if (mji?.value == true) {
return mji.jsonIgnore as A // this cast should be safe because we have checked
// the annotation class
}
}
return super._findAnnotation(annotated, annoClass)
}
}
我已经用以下课程对此进行了测试
I've tested this with the following class
class Test {
@MyJsonIgnore
val ignoreMe = "IGNORE"
val field = "NOT IGNORE"
}
和方法
fun main() {
println(Mappers.myMapper().writeValueAsString(Test()))
println(ObjectMapper().writeValueAsString(Test()))
}
输出是
{"field":"NOT IGNORE"}
{"ignoreMe":"IGNORE","field":"NOT IGNORE"}
这篇关于如何正确覆盖 JacksonAnnotationIntrospector._findAnnotation 以替换元素的注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!