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
}
By default, Gson serializes enums by name in lowercase. If this is not sufficient and you want some other string or an integer value, then have a look at the @SerializedName annotation. Gson can serialize and deserialize enums using the @SerializedName annotation.
Introduction. Gson is the main actor class of Google Gson library. It provides functionalities to convert Java objects to matching JSON constructs and vice versa. Gson is first constructed using GsonBuilder and then toJson(Object) or fromJson(String, Class) methods are used to read/write JSON constructs.
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 <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; } } }
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 <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;
}
}
}
Usage:
@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));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With