java - JSR269注解处理 getElementsAnnotatedWith() 每次循环返回所有带注解的元素并且无法区分它属于哪种类型

标签 java annotation-processing

最近,我对 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/

相关文章:

java - 一段时间内出现网络问题时,客户端与远程 Hbase 服务器的连接

java - GWT 客户端 : java. util 还是 com.google.gwt.dev.util?

java - 如何生成 JPA 实体元模型?

java - 使用元注释触发注释处理器

java - 注释处理器似乎破坏了 Java 泛型

java - 无法弄清楚为什么我会得到不兼容的类型

java - 使用selenium下载文件

java - 注解处理器@autoservice

kotlin - 如何从RoundEnvironment获取适当的kotlin类型以用于自定义注释处理器?

java - 在 Scala 中,是否有一种安全、快捷的方式将 InputStream 写入文件?