serialize enum fields with gson

By default, Gson just serialize the ‘name’ of the Enum which might not be enough since we might need also want to carry all the fields during the serialization. To achieve this we need to has our own gson adaptor and make use of 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:
Enum class:

public enum ReportTypes
{
    SP(1), CA(2), ADF(3), ORF(4), CTO(5), CDS(6), TSP(7);

    private int reportTypeId;
    ReportTypes(int reportTypeId)
    {
        this.reportTypeId = reportTypeId;
    }

    public int getReportTypeId()
    {
        return reportTypeId;
    }
}

Test Code:

    @Test
    public void testReportTypesGsonSerialization()
    {
        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapterFactory(new EnumAdapterFactory());
        Gson gson = builder.create();
        System.out.println(gson.toJson(ReportTypes.values()));
    }

Result:

[
  {
    "value": "SP",
    "reportTypeId": "1"
  },
  {
    "value": "CA",
    "reportTypeId": "2"
  },
  {
    "value": "ADF",
    "reportTypeId": "3"
  },
  {
    "value": "ORF",
    "reportTypeId": "4"
  },
  {
    "value": "CTO",
    "reportTypeId": "5"
  },
  {
    "value": "CDS",
    "reportTypeId": "6"
  },
  {
    "value": "TSP",
    "reportTypeId": "7"
  }
]

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s