枚举类 json格式 的正反转化

本文探讨了Java枚举类与JSON之间的转换问题。当使用@JsonValue注解时,会影响枚举对象转JSON的结果。默认情况下,枚举名字会被转换;若注解在integer字段上,会导致数字类型的值被当作索引转换,可能引发错误。解决方法是将integer字段改为string,确保枚举值与索引对应。此外,文章还提醒了注意事项,如保持枚举值的顺序与索引一致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

枚举类 json格式 的正反转化

例如有以下枚举:

@AllArgsConstructor //lombok的有参构造注解
public enum TestEnum {
    AAA(0,"AAAa"),
    BBB(1,"BBBb"),
    CCC(2,"CCCc"),
    DDD(4,"DDDd");
    
    @JsonValue
    private Integer id;
    private String name;
}
  1. 默认不加 @JsonValue 注解时,以枚举对象的名字转json

AAA(0,“AAAa”), 转json后 “AAA”

  1. 给某个字段加@JsonValue注解时,如给name字段加@JsonValue注解

AAA(0,“AAAa”), 转json后 “AAAa”

  • 但是 如果这个字段是integer类型的,如给Integer id字段加@JsonValue注解

DDD(4,“DDDd”), 转json后 4 (注意我的4 没有带引号 这个4是数字类型)

数字类型的4反转枚举类时,会把4当做索引去找枚举对象
四个枚举对象索引为[0,1,2,3] 数字类型4反转时会报错

解决办法:

  1. 将 Integer id 改为 String id 这样最好
  2. 保证每个枚举对象 integer id 的值 和索引值对应(自上而下 从0开始) 这样很局限
### 解决方案 要将包含枚举类型的实体类正确序列化为 JSON,可以采用不同的方法来应对不同编程语言中的需求。以下是针对 Java 和 C# 中常见场景的具体解决方案。 #### 1. **Java (FastJson)** 在 FastJson 中处理 Enum 类型的序列化问题可以通过自定义 `SerializeFilter` 或者调整配置选项完成。根据引用描述[^1],FastJson 默认会尝试将 Enum 属性作为字符串返回到前端并保存至数据库中。如果需要更复杂的控制,则需引入自定义逻辑: ```java import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.ValueFilter; public class EnumSerializationExample { public static void main(String[] args) { MyEntity entity = new MyEntity(); entity.setType(MyEnum.TYPE_A); ValueFilter filter = (object, name, value) -> { if (value instanceof MyEnum) { return ((MyEnum)value).name(); // 自定义序列化的字段值 } return value; }; String jsonString = JSON.toJSONString(entity, filter); System.out.println(jsonString); // 输出结果 {"type":"TYPE_A"} } enum MyEnum { TYPE_A, TYPE_B }; static class MyEntity { private MyEnum type; public MyEnum getType() { return this.type; } public void setType(MyEnum type) { this.type = type; } } } ``` 上述代码通过 `ValueFilter` 定义了如何将 Enum 转换为特定形式的字符串表示。 --- #### 2. **Gson (Java)** 对于 Gson 来说,虽然其内置机制不直接支持多类型 Enum 的统一序列化/反序列化,但可通过扩展实现通用功能。基于引用[^2]提到的内容,可设计一个泛型适配器用于多种 Enum 处理: ```java import com.google.gson.*; class GenericEnumAdapter<T extends Enum<T>> implements JsonSerializer<T>, JsonDeserializer<T> { @Override public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { Class<T> clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; try { return Enum.valueOf(clazz, json.getAsString()); } catch(IllegalArgumentException e){ throw new JsonSyntaxException("Unknown element value: " + json.getAsJsonPrimitive(),e); } } @Override public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(src.name()); // 使用 Enum 名称进行序列化 } } // 注册 Adapter 并测试 Gson gson = new GsonBuilder() .registerTypeHierarchyAdapter(Enum.class,new GenericEnumAdapter<MyEnum>()) .create(); System.out.println(gson.toJson(new MyEntity())); // 输出 {"type":"TYPE_A"} ``` 此部分实现了动态适应各种 Enum 子类的能力,而无需重复注册多个 Serializer。 --- #### 3. **C#** 当涉及 C# 编程环境下的 JSON 反序列化时,尤其是面对键值可能冲突的情况(如保留字),则应考虑手动指定映射关系或者改造数据结构。依据引用[^3]^,下面展示了一种可行策略——利用 `[JsonProperty]` 特性标注目标成员变量: ```csharp using Newtonsoft.Json; using System; namespace ConsoleApp { public enum SiteTypeEnum { Home, AboutUs /* 关键词 */ , Contact } public class ExampleDataModel { [JsonProperty(PropertyName="about_us")] // 避免直接使用 'AboutUs' 导致解析失败 public SiteTypeEnum PageType { get; set; } public string Title { get; set; } } internal class Program { static void Main(string[] args) { var jsonData = "{\"about_us\":\"Home\",\"Title\":\"Sample\"}"; var deserializedObject = JsonConvert.DeserializeObject<ExampleDataModel>(jsonData); Console.WriteLine(deserializedObject.PageType.ToString()); // Output: Home } } } ``` 这里展示了如何借助第三方库 NewtonSoft.Json 提供的功能规避潜在命名冲突风险。 另外,在某些特殊情况下也可以参考引用[^4]给出的方法来自动生成完整的 JavaScript 对象数组表达式,从而间接达到目的。 --- ### 总结 以上分别介绍了三种主流开发平台下有关复杂枚举类型向 JSON 数据格式转化的技术手段及其实际应用案例。每一种都有各自特点以及适用范围,请根据项目具体情况选取合适的方式加以实施。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值