可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I've this enum:
enum RequestStatus { OK(200), NOT_FOUND(400); private final int code; RequestStatus(int code) { this.code = code; } public int getCode() { return this.code; } };
and in my Request-class, I have this field: private RequestStatus status.
When using Gson to convert the Java object to JSON the result is like:
"status": "OK"
How can I change my GsonBuilder or my Enum object to give me an output like:
"status": { "value" : "OK", "code" : 200 }
回答1:
You can use something like this:
GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapterFactory(new MyEnumAdapterFactory());
or more simply (as Jesse Wilson indicated):
GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(RequestStatus.class, new MyEnumTypeAdapter());
and
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; } } }
回答2:
In addition to Polet's answer, if you need a generic Enum serializer, you can achieve it via 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; } } }
Usage:
@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)); }