让Gson使用枚举字符串值,而不是常量名称。

huangapple go评论182阅读模式
英文:

Make Gson to use Enum string value instead of constant name

问题

以下是您提供的内容的翻译部分:

有没有办法告诉 Gson 使用字符串值本身,而不是其 Java 常量名称?
理想情况下在 Gson 配置中进行全局设置,这样它会对所有枚举类型执行此操作。

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Main {
  public static class Dress {
    public Color color;
  }

  public static enum Color {
    RED("red"),
    BLUE("blue");

    private final String type;
    Color(final String type) { this.type = type; }

    public String toString() { return type; }
  }

  public static void main(String[] args) throws InterruptedException {
    Dress dress = new Dress();
    dress.color = Color.RED;

    GsonBuilder builder = new GsonBuilder();
    builder.setPrettyPrinting();
    Gson gson = builder.create();
    System.out.println(gson.toJson(dress));
    // ==> { "color": "RED" }
  }
}

它输出的是 { "color": "RED" } 而不是 { "color": "red" }

英文:

Is there a way to tell Gson to use the string value itself, not its Java constant name?
Ideally globally in Gson config, so it would do that for all enums.

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Main {
  public static class Dress {
    public Color color;
  }

  public static enum Color {
    RED("red"),
    BLUE("blue");

    private final String type;
    Color(final String type) { this.type = type; }

    public String toString() { return type; }
  }

  public static void main(String[] args) throws InterruptedException {
    Dress dress = new Dress();
    dress.color = Color.RED;

    GsonBuilder builder = new GsonBuilder();
    builder.setPrettyPrinting();
    Gson gson = builder.create();
    System.out.println(gson.toJson(dress));
    // ==> { "color": "RED" }
  }
}

It prints { "color": "RED" } instead of { "color": "red" }.

答案1

得分: 5

使用@SerializedName设置序列化值

import com.google.gson.annotations.SerializedName;

public static enum Color {
    @SerializedName("red")
    RED("red"),
    @SerializedName("blue")
    BLUE("blue");
    ...
}

另一种方法是使用自定义序列化器

class ColorSerializer implements JsonSerializer {
   @Override
   public JsonElement serialize(Color src, Type typeOfSrc, JsonSerializationContext context) {
      return new JsonPrimitive(src.toString());
   }
}

并在构建器中注册自定义序列化器

builder.registerTypeAdapter(Color.class, new ColorSerializer());
英文:

Use @SerializedName with serialization value

import com.google.gson.annotations.SerializedName;

public static enum Color {
    @SerializedName("red")
    RED("red"),
    @SerializedName("blue")
    BLUE("blue");
    ...
}

Another way is using a custom serializer

class ColorSerializer implements JsonSerializer {
   @Override
   public JsonElement serialize(Color src, Type typeOfSrc, JsonSerializationContext context) {
      return new JsonPrimitive(src.toString());
   }
}

And register custom serializer in builder

builder.registerTypeAdapter(Color.class, new ColorSerializer());

答案2

得分: 2

创建一个自定义的序列化器,例如:

public class EnumSerializer<T extends Enum<T>> implements JsonSerializer<T> {
    @Override
    public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(src.toString());
    }
}

像这样进行注册:

builder.registerTypeAdapter(Color.class, new EnumSerializer<>());
// 这里使用泛型的原因是可以轻松地将其注册到其他枚举类型,例如:
// builder.registerTypeAdapter(SomeEnum.class, new EnumSerializer<>());

如果你需要将它应用于多个枚举类型或所有枚举类型,且不希望为每个枚举类型单独注册,你可以使用 TypeAdapterFactory(稍微复杂一些)。首先,你需要创建 TypeAdapter:

public class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
    @Override
    public void write(JsonWriter out, T value) throws IOException {
        out.jsonValue(value.toString());
    }
    @Override
    public T read(JsonReader in) throws IOException {
        return null;
    }
}

然后是工厂类:

public static class EnumTypeAdapterFactory implements TypeAdapterFactory {
    @Override
    // 实际上将 EnumTypeAdapter 设为非泛型可能会更简单
    // 但另一方面,在其他上下文和其他方式中使用时可能会更好。因此这些抑制警告
    @SuppressWarnings({"rawtypes", "unchecked"})
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        // 这个条件适用于所有枚举类型。如果不需要,可以进行更改。
        if (Enum.class.isAssignableFrom(type.getRawType())) {
            return new EnumTypeAdapter();
        } else {
            return null;                
        }
    }
}

然后进行注册:

builder.registerTypeAdapterFactory(new EnumTypeAdapterFactory());
英文:

Create a custom serializer like:

public class EnumSerializer&lt;T extends Enum&lt;T&gt;&gt;
                    implements JsonSerializer&lt;T&gt; {
    @Override
    public JsonElement serialize(T src, Type typeOfSrc,
                JsonSerializationContext context) {
        return new JsonPrimitive(src.toString());
    }
}

Register it like:

builder.registerTypeAdapter(Color.class, new EnumSerializer&lt;&gt;());
// there is a reason for generics: that way you can easily register it to 
// other Enum types also, for example:
// builder.registerTypeAdapter(SomeEnum.class, new EnumSerializer&lt;&gt;());

If you need to apply it to a more than one or all Enum and you do not wish to register it separately to each one you can use TypeAdapterFactory (bit more complicated). First you need the TypeAdapter:

public class EnumTypeAdapter&lt;T extends Enum&lt;T&gt;&gt; extends TypeAdapter&lt;T&gt; {
    @Override
    public void write(JsonWriter out, T value) throws IOException {
        out.jsonValue(value.toString());
    }
    @Override
    public T read(JsonReader in) throws IOException {
        return null;
    }
}

Then the factory:

public static class EnumTypeAdapterFactory implements TypeAdapterFactory {
    @Override
    // Actually it might be easier to just make EnumTypeAdapter non-generic
    // but on the other hand it might be better if used in some other contexts
    // and in some other ways. Thus these suppressions
    @SuppressWarnings({&quot;rawtypes&quot;, &quot;unchecked&quot;})
    public &lt;T&gt; TypeAdapter&lt;T&gt; create(Gson gson, TypeToken&lt;T&gt; type) {
        // This if applies to all Enums. Change if not wanted.            
        if(Enum.class.isAssignableFrom(type.getRawType())) {
            return new EnumTypeAdapter();
        } else {
            return  null;                
        }
    }
}

and register it:

builder.registerTypeAdapterFactory(new EnumTypeAdapterFactory());

huangapple
  • 本文由 发表于 2020年7月24日 01:33:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/63059972.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定