如何在运行时将Java Enum转换为Json?

时间:2012-10-08 12:59:49

标签: java json reflection enums annotations

我有一个枚举如下:

public enum SomeType {
    SOME_KEY (some-display-value-as-label);
    private String label;

    private SomeType(String label){
        this.label=label;
    }
    public String getLabel() {
        return label;
    }
    public void setLabel(String value) {
        this.label = value;
    }
}

现在我正在使用谷歌反射库,并提出了一个自定义注释,我在上面标记了枚举,如@makejson。

我们的想法是使用@makejson注释对所有类的反射进行应用启动扫描,然后为每个枚举生成json对象。

我正在尝试做的是在启动课程中:

Reflections reflections = new Reflections("my.package.name");
Set<Class<?>> annotatedClasses = reflections.getTypesAnnotatedWith(MakeJson.class);
    for (Class<?> annotated : annotatedClasses) {
        if  (annotated.isEnum()) {
            MakeJson j = annotated.getAnnotation(MakeJson.class);
            Object[] constants = annotated.getEnumConstants();
            Method[] methods = annotated.getMethods();
            Method getValue = null;
            for (Method m : methods) {
                if ("valueOf".equals(m.getName())) {
                    getValue = m; //get Reference of valueOf method
                    break;
                }    
            }
            //List<Object> labels = Arrays.asList(m.invokem.getReturnType().isEnum()(annotated));
            for (Object constant : constants) {
                System.out.println(constant.toString());
                System.out.println(getValue.invoke(annotated,constant.toString()));
            }
        }
    }

此代码断开以下异常:线程“main”中的异常java.lang.IllegalArgumentException:参数数量错误

非常感谢任何帮助。最终目标是能够为SomeType {SOME_KEY:“display-value”}获取json对象。为此,我无法使用Reflection获取枚举常量的值。

3 个答案:

答案 0 :(得分:2)

我之前的回答是错误的。这里发生的是Enum类定义了public static valueOf(Class<?>, String)方法。当java编译器将您的enum SomeType转换为类时,它将生成public class SomeType extends Enum<SomeType>,并将向您的valueOf(String)类添加另一个SomeType方法。因此,您最终会在类中使用名为“valueOf”的两个方法。对我来说,您实际上是在呼叫valueOf(Class, String),但实际上打算致电valueOf(String)

要解决此问题,请从以下位置更改循环:

Method[] methods = annotated.getMethods();
Method getValue = null;
for (Method m : methods) {
    if ("valueOf".equals(m.getName())) {
        getValue = m; //get Reference of valueOf method
        break;
    }    
}

Method getValue = annotated.getMethod("valueOf", new Class<?>[]{String.class});

然后应修复您的问题。

答案 1 :(得分:1)

这个怎么样:

    Map tmp = new HashMap<SomeType, String>();
    for(SomeType type : SomeType.values()){
        tmp.put(type, type.getLabel());
    }
    String desiredJson = new Gson().toJson(tmp);

答案 2 :(得分:0)

所以这就是我最终做的事情: 我修改了@makejson注释以包含一个名为label的字段,该字段是必需的,应该设置为可以在枚举中返回与SOME_KEY相关的描述的方法。

这是注释的样子:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MakeJson {
    String label();
}

所以enum声明中的注释看起来像     @makejson(标记= “getLabel”)     public enum SomeType {         ...... //与上面的问题相同     }

然后在解析类中,我只是从注释的方法中获取此方法并调用它以获得正确的常量:

    Reflections reflections = new Reflections("my.package.name");
    Set<Class<?>> annotatedClasses = reflections.getTypesAnnotatedWith(MakeJson.class);
    for (Class<?> annotated : annotatedClasses) {
        if  (annotated.isEnum()) {
            Jsonify j = annotated.getAnnotation(MakeJson.class);
            Object[] constants = annotated.getEnumConstants();
            Method m = annotated.getMethod(j.label()); // get the method name
            for (Object constant : constants) {
                System.out.println(constant.toString());
                System.out.println(m.invoke(constant));
                // construct json object here
            }
        }
    }

所以最后我通过使用注释在运行时插入此信息来规避无法使用反射调用方法的问题!