Using Enums While Parsing JSON with Gson

Using Enums while parsing JSON with GSON

From the documentation for Gson:

Gson provides default serialization and deserialization for Enums... If you would prefer to change the default representation, you can do so by registering a type adapter through GsonBuilder.registerTypeAdapter(Type, Object).

Following is one such approach.

import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.List;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;

public class GsonFoo
{
public static void main(String[] args) throws Exception
{
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(AttributeScope.class, new AttributeScopeDeserializer());
Gson gson = gsonBuilder.create();

TruncateElement element = gson.fromJson(new FileReader("input.json"), TruncateElement.class);

System.out.println(element.lower);
System.out.println(element.upper);
System.out.println(element.delimiter);
System.out.println(element.scope.get(0));
}
}

class AttributeScopeDeserializer implements JsonDeserializer<AttributeScope>
{
@Override
public AttributeScope deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
AttributeScope[] scopes = AttributeScope.values();
for (AttributeScope scope : scopes)
{
if (scope.scope.equals(json.getAsString()))
return scope;
}
return null;
}
}

class TruncateElement
{
int lower;
int upper;
String delimiter;
List<AttributeScope> scope;
}

enum AttributeScope
{
TITLE("${title}"), DESCRIPTION("${description}");

String scope;

AttributeScope(String scope)
{
this.scope = scope;
}
}

Setting default Enum while parsing using Gson

I have two options.

  1. Make Status be String

  2. Use Gson custom deserializer like this(Kotlin example).

    class StatusDeserializer : JsonDeserializer<Status> {
    override fun deserialize(
    json: JsonElement,
    typeOfT: Type,
    context: JsonDeserializationContext
    ): Status {
    val jsonObject = json.asJsonObject
    return when(jsonObject.get("status").asString) {
    "A", "B", "C", "D" -> context.deserialize<Status>(jsonObject, Status::class.java)
    else -> Status.DEFAULT
    }
    }
    }

    val gson = GsonBuilder().registerTypeAdapter(Status::class.java, StatusDeserializer()).create()

serialize and deserialize enum with Gson

According to Gson API documentation, Gson provides default serialization/deserialization of Enum, so basically it should be serialized and deserialized using the standard toJson and fromJson methods, as with any other type.

Serializing a map of enums with Gson with custom serialization

Gson uses a dedicated serializer for Map keys. This, by default, use the toString() of the object that's about to be used as a key. For enum types, that's basically the name of the enum constant. @SerializedName, by default for enum types, will only be used when serialized the enum as a JSON value (other than a pair name).

Use GsonBuilder#enableComplexMapKeySerialization to build your Gson instance.

private static Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();

GSON. workaround for enum and int

Using an answer from Chin and help from my workmate I get following solution.

I wrote an inner class in the parser class.

private static class ObjectTypeDeserializer implements
JsonDeserializer<ObjectTypeEnum>
{
@Override
public PreconditioningStatusEnum deserialize(JsonElement json,
Type typeOfT, JsonDeserializationContext ctx)
throws JsonParseException
{
int typeInt = json.getAsInt();
return ObjectTypeEnum
.findByAbbr(typeInt);
}
}

and created GSON-Object on following way:

    GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(ObjectTypeEnum.class, new ObjectTypeDeserializer() );
Gson gson = gsonBuilder.create();

http://sites.google.com/site/gson/gson-user-guide#TOC-Custom-Serialization-and-Deserializ

How to parse JSON objects into an enum

You can create a deserializer for TspEnum:

class TspDeserializer : JsonDeserializer<TspEnum> {
override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): TspEnum {
val stringValue = json.asString
for (enum in TspEnum.values()) {
if (enum.provider == stringValue) {
return enum
}
}
throw IllegalArgumentException("Unknown tsp $stringValue!")
}
}

next you have to register it:

val gson = GsonBuilder()
.registerTypeAdapter(TspEnum::class.java, TspDeserializer())
.create()

and then you can parse your user:

val user = gson.fromJson(json, User::class.java)
println(user) // prints User(tsp=AY_BEE_CEE, userId=lkajsdlk-199191-lkjdflakj)


Related Topics



Leave a reply



Submit