Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gson Serializetion Bug in Enum Map #1920

Open
phooeny opened this issue Jul 15, 2021 · 1 comment
Open

Gson Serializetion Bug in Enum Map #1920

phooeny opened this issue Jul 15, 2021 · 1 comment
Labels

Comments

@phooeny
Copy link

phooeny commented Jul 15, 2021

When the enum type is used as the key of one map, if there is @SerializedName("name") at the declaration of the enum items, the Gson serialization and deserialization do NOT work well.

Following is the bad case

import com.google.gson.annotations.SerializedName;

public enum RoomIdentifier {
    @SerializedName("MARKER_NAME")  // Here is the bad case
    ROOM_NAME;
}

Test code is here

    public void testConvert() {
        RoomIdentifier id = RoomIdentifier.ROOM_NAME;
        
        Map<RoomIdentifier, String> slots = new HashMap<SlotIdentifier, String>();
        slots.put(RoomIdentifier.ROOM_NAME,"ROOM_NAME_TEST");
        
        String strSerialized = gson.toJson(slots);

        Type type = new TypeToken<Map<RoomIdentifier, String>>() {
        }.getType();
        Map<RoomIdentifier, String> slotsDeserialized = gson.fromJson(strSerialized, type);
        
        System.out.println(gson.toJson(id));   // "MARKER_NAME"   //As expect, SerializedName is used
        System.out.println(strSerialized);                // {"ROOM_NAME":"ROOM_NAME_TEST"}   // the key name is not SerializedName
        System.out.println(slotsDeserialized);            // {null=ROOM_NAME_TEST}    //The key is null
    }

Root cause

  • In the serialization function GSON::toJson , the MapTypeAdapterFactory::Adapter uses String.valueOf(entry.getKey()) to generate the key. @SerializedName("name") ("MARKER_NAME" in the example) is NOT used at all. Here is Gson code
  • But in the deserialization function GSON::fromJson , EnumTypeAdapter is used to deserialize the key(here is code). If one field is marked by @SerializedName("name") , the original name string ("ROOM_NAME" in the example ) could NOT be recognized, null is returned.
@Marcono1234
Copy link
Collaborator

Marcono1234 commented Jul 17, 2021

Relates to #127, #1722
Duplicate of #473, #1011

It is unfortunate that Gson uses String.valueOf for map keys, since this behavior is not obvious to the user and most likely not symmetric with deserialization, as shown here.

Personally I think it would make sense to special-case enums for map key serialization since it is guaranteed that they have a String value. To remain as backward compatible as possible, by default String.valueOf could be used for enums as well (which is equivalent to Enum.name(), unless overridden), but if the enum constant is annotated with @SerializedName, then its value should be used. This should in most cases not cause any issues, even when Enum.toString() is overridden and used intentionally by the user for serialization.
Note however, that I am not a member of this project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants