Gson:如何改变Enum的输出
我有这个枚举 :
enum RequestStatus { OK(200), NOT_FOUND(400); private final int code; RequestStatus(int code) { this.code = code; } public int getCode() { return this.code; } };
在我的Request-class中,我有这个字段: private RequestStatus status
。
使用Gson将Java对象转换为JSON时,结果如下:
"status": "OK"
如何更改我的GsonBuilder或我的Enum对象,为我提供如下输出:
"status": { "value" : "OK", "code" : 200 }
你可以使用这样的东西:
GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapterFactory(new MyEnumAdapterFactory());
或者更简单(正如Jesse Wilson所说):
GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(RequestStatus.class, new MyEnumTypeAdapter());
和
public class MyEnumAdapterFactory implements TypeAdapterFactory { @Override public TypeAdapter create(final Gson gson, final TypeToken type) { Class super T> rawType = type.getRawType(); if (rawType == RequestStatus.class) { return new MyEnumTypeAdapter (); } return null; } public class MyEnumTypeAdapter extends TypeAdapter { 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; } } }
除了Polet的答案,如果你需要一个通用的Enum序列化器 ,你可以通过reflection实现它:
public class EnumAdapterFactory implements TypeAdapterFactory { @Override public TypeAdapter create(final Gson gson, final TypeToken type) { Class super T> rawType = type.getRawType(); if (rawType.isEnum()) { return new EnumTypeAdapter (); } return null; } public class EnumTypeAdapter extends TypeAdapter { @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 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)); }