最近,我对 JSR-269 注解处理很感兴趣,我想编写一个 lib 来消除一些样板代码,例如 json 处理。我真的生成了代码,但是,我遇到了一个致命的问题,花了很多时间却无法解决它。
问题是,RoundEnvironment.getElementsAnnotatedWith()
方法总是返回所有用注释注释的元素,我无法区分哪个元素来自特定的类。可能问题没说清楚。我向您展示下面的代码。
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface JsonObject {
}
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface JsonField {
String value() default "";
}
@JsonObject
public class Name {
@JsonField("last") public String last;
@JsonField("first") public String first;
}
@JsonObject
public class User {
@JsonField("age") public int age;
@JsonField("name") public String name;
@JsonField("sex") public boolean sex;
}
前2个是注释,JsonObject
指示注释类型是 JsonObject 且 JsonField
表示被注解的字段是一个json字段。
后 2 个是我想要生成 json 解析代码的示例 POJO 类。
在 Processor
类,AbstractProcessor.process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
方法,当我调用roundEnv.roundEnv.getElementsAnnotatedWith(JsonField.class)
时每个 type( Name
, User
) 循环,返回结果为所有 json 字段,在上面的示例中,结果为 ["last", "first", "age", "name", "性别”]。在这种情况下,我无法区分哪个字段属于哪个 POJO。
也许这些话无法解释我的意思。这是我在 process
中所做的事情方法。
// the set[Name, User]
Set<? extends Element> jsonObjects = roundEnv.getElementsAnnotatedWith(JsonObject.class);
for (Element jsonObject : jsonObjects) {
// the set[last, first, age, name, sex], **THIS IS THE PROBLEM**
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(JsonField.class);
// other stuff...
}
如有任何我未提及或不清楚的问题,请随时询问我。任何建议表示赞赏,提前致谢!
最佳答案
您可以通过调用 getElementsAnnotatedWith(JsonField.class)
方法构建 json 对象元素的集合,并根据封闭元素的注释对结果进行归档。
这是一个完整的示例(为了简单起见,使用运行时注释处理):
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes("*")
public class ElementFilterProcessor extends AbstractProcessor {
@Retention(RetentionPolicy.RUNTIME)
public static @interface JsonObject {}
@Retention(RetentionPolicy.RUNTIME)
public static @interface JsonField { String value(); }
@JsonObject
public class Name {
@JsonField("last") public String last;
@JsonField("first") public String first;
}
@JsonObject
public class User {
@JsonField("age") public int age;
@JsonField("name") public String name;
@JsonField("sex") public boolean sex;
}
public static void main(String[] args) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
final JavaCompiler.CompilationTask task = compiler.getTask(
null,
null,
null,
null,
Collections.singleton(ElementFilterProcessor.class.getName()),
Collections.EMPTY_SET);
task.setProcessors(Collections.singleton(new ElementFilterProcessor()));
task.call();
}
@Override
public boolean process(
final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
return true;
}
final Set<? extends Element> jsonFields =
roundEnv.getElementsAnnotatedWith(JsonField.class);
final Map<Element, List<Element>> jsonObjects = new HashMap<>();
for (final Element element : jsonFields) {
final Element classElement = element.getEnclosingElement();
if (classElement.getAnnotation(JsonObject.class) != null) {
List<Element> list = jsonObjects.get(classElement);
if (list == null) {
list = new ArrayList<>();
jsonObjects.put(classElement, list);
}
list.add(element);
}
}
System.out.println(jsonObjects);
return false;
}
}
输出:
{stackoverflow.annotation.ElementFilterProcessor.User=[age, name, sex], stackoverflow.annotation.ElementFilterProcessor.Name=[last, first]}
我还建议考虑使用第三方库将 Java 对象映射到 JSON。例如,the Jackson processor
关于java - JSR269注解处理 getElementsAnnotatedWith() 每次循环返回所有带注解的元素并且无法区分它属于哪种类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27210759/