JSR269批注处理getElementsAnnotatedWith()在每个循环中返回所有被批注的元素,并且无法区分它属于哪种类型

龙凯

最近,我对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字段。

后两个是我想要粘贴json-parse代码的示例POJO类。

Processor该类的AbstractProcessor.process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)方法中,当我循环调用roundEnv.roundEnv.getElementsAnnotatedWith(JsonField.class)每个type(NameUser)时,返回结果是所有json字段,在上面的示例中,结果是[“ last”,“ first”,“ age”,“名称”,“性别”]。在这种情况下,我无法区分哪个字段属于哪个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...
}

随意问我任何我未提及或不清楚的内容。任何建议表示赞赏,在此先感谢!

阿列克谢·加夫里洛夫(Alexey Gavrilov)

您可以通过调用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。例如,杰克逊处理器

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

Related 相关文章

热门标签

归档