2012-04-24 82 views
26

的输出我有这个枚举GSON:如何更改枚举

enum RequestStatus { 
    OK(200), NOT_FOUND(400); 

    private final int code; 

    RequestStatus(int code) { 
    this.code = code; 
    } 

    public int getCode() { 
    return this.code; 
    } 
}; 

,在我的请求一流的,我有这样的领域:private RequestStatus status

当使用GSON到Java对象到JSON转换的结果是这样的:

"status": "OK" 

我怎样才能改变我的GsonBuilder或我的枚举对象给我等的输出:

"status": { 
    "value" : "OK", 
    "code" : 200 
} 

回答

18

你可以使用这样的东西:

GsonBuilder builder = new GsonBuilder(); 
builder.registerTypeAdapterFactory(new MyEnumAdapterFactory()); 

或更简单地(如杰西威尔逊指出):

GsonBuilder builder = new GsonBuilder(); 
builder.registerTypeAdapter(RequestStatus.class, new MyEnumTypeAdapter()); 

public class MyEnumAdapterFactory implements TypeAdapterFactory { 

    @Override 
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) { 
      Class<? super T> rawType = type.getRawType(); 
      if (rawType == RequestStatus.class) { 
       return new MyEnumTypeAdapter<T>(); 
      } 
      return null; 
    } 

    public class MyEnumTypeAdapter<T> extends TypeAdapter<T> { 

     public void write(JsonWriter out, T value) throws IOException { 
       if (value == null) { 
        out.nullValue(); 
        return; 
       } 
       RequestStatus status = (RequestStatus) value; 
       // Here write what you want to the JsonWriter. 
       out.beginObject(); 
       out.name("value"); 
       out.value(status.name()); 
       out.name("code"); 
       out.value(status.getCode()); 
       out.endObject(); 
     } 

     public T read(JsonReader in) throws IOException { 
       // Properly deserialize the input (if you use deserialization) 
       return null; 
     } 
    } 

} 
+0

@ DennisMadsen在这里,我把它作为代码的内部类。你错过了吗,或者我不明白你的问题? – 2012-04-24 12:24:43

+0

谢谢。你可以给我一个例子,我如何在写入方法中更改* JsonWriter *? – dhrm 2012-04-24 12:33:11

+0

@DennisMadsen我添加了一些示例代码,我认为它们几乎是你正在寻找的。 – 2012-04-24 12:39:33

2

除了波莱的答案,如果你需要一个通用枚举串行,您可以通过反射实现它:

public class EnumAdapterFactory implements TypeAdapterFactory 
{ 

    @Override 
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) 
    { 
     Class<? super T> rawType = type.getRawType(); 
     if (rawType.isEnum()) 
     { 
      return new EnumTypeAdapter<T>(); 
     } 
     return null; 
    } 

    public class EnumTypeAdapter<T> extends TypeAdapter<T> 
    { 
     @Override 
     public void write(JsonWriter out, T value) throws IOException 
     { 
      if (value == null || !value.getClass().isEnum()) 
      { 
       out.nullValue(); 
       return; 
      } 

      try 
      { 
       out.beginObject(); 
       out.name("value"); 
       out.value(value.toString()); 
       Arrays.stream(Introspector.getBeanInfo(value.getClass()).getPropertyDescriptors()) 
         .filter(pd -> pd.getReadMethod() != null && !"class".equals(pd.getName()) && !"declaringClass".equals(pd.getName())) 
         .forEach(pd -> { 
          try 
          { 
           out.name(pd.getName()); 
           out.value(String.valueOf(pd.getReadMethod().invoke(value))); 
          } catch (IllegalAccessException | InvocationTargetException | IOException e) 
          { 
           e.printStackTrace(); 
          } 
         }); 
       out.endObject(); 
      } catch (IntrospectionException e) 
      { 
       e.printStackTrace(); 
      } 
     } 

     public T read(JsonReader in) throws IOException 
     { 
      // Properly deserialize the input (if you use deserialization) 
      return null; 
     } 
    } 
} 

用法:

@Test 
public void testEnumGsonSerialization() 
{ 
    List<ReportTypes> testEnums = Arrays.asList(YourEnum.VALUE1, YourEnum.VALUE2); 
    GsonBuilder builder = new GsonBuilder(); 
    builder.registerTypeAdapterFactory(new EnumAdapterFactory()); 
    Gson gson = builder.create(); 
    System.out.println(gson.toJson(reportTypes)); 
} 
+1

这很好,但要小心,它会对getter进行序列化,而不是Enum的字段。 – 2016-10-05 09:55:20