V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
daiwenzh5
V2EX  ›  Java

Java 中使用枚举参数,如何进行 JSR303 校验意外值? 或者说参数是否直接使用枚举类型

  •  
  •   daiwenzh5 · 2022-08-05 15:22:32 +08:00 · 2437 次点击
    这是一个创建于 827 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Java 中使用枚举参数,如何进行 JSR303 校验意外值?

    如题,使用枚举直接接收参数,使用 json 反序列化,对于意外值会接收成 null ,如此实际的参数已经丢失了,只能判断是否为 null 。

    enum Sex {
     MALE(1),
     
     FEMALE(0)
    }
    

    像这样的枚举值,如果参数为 2 、3 或其他任意值,在不进行自定义序列化时,接收会报错,但是自定义序列化后,只有 null 以及合法枚举。

    预期的目标,使用参数校验,提示“性别可选值 [ 1 ,0 ] ”。

    使用原始类型接收,可以实现,但如何直接使用枚举类型实现。

    现在测试结果,可以在运行时动态添加一个 UNKNOWN 类型的枚举值,用于映射非预期值。

    但感觉太重了。

    或者换个问题,参数使用原始值,还是枚举值较好

    18 条回复    2022-08-06 17:48:37 +08:00
    RainCats
        1
    RainCats  
       2022-08-05 15:31:20 +08:00
    前端直接传数字进来的话,反序列化不是根据你定义的 code 值,是根据枚举的 ordinal ,也就是从零开始的次序来找的枚举。你得自己重写枚举反序列化的东西才行
    ql562482472
        2
    ql562482472  
       2022-08-05 15:33:47 +08:00
    用“ MALE”“ FEMALE” 拒绝数字定义
    sulinwork
        3
    sulinwork  
       2022-08-05 19:25:45 +08:00
    可以定义一个枚举的统一接口 在写一个枚举的 json 适配器就行了
    oneisall8955
        4
    oneisall8955  
       2022-08-05 20:39:30 +08:00 via Android
    用字符串接受,值是 enum.name(),就是字面上定义的字符串,另外,值对不上 springboot 用 jackson 反序列化默认会报错
    mmdsun
        5
    mmdsun  
       2022-08-05 22:03:14 +08:00
    jsr-303 可以自定义校验注解,自己写个就好
    daiwenzh5
        6
    daiwenzh5  
    OP
       2022-08-05 23:46:14 +08:00
    @sulinwork 这样用校验器就没法区分出非预取值了,因为匹配不上的就被转成 null 了
    daiwenzh5
        7
    daiwenzh5  
    OP
       2022-08-05 23:48:41 +08:00
    @oneisall8955 用原始值感觉不够优雅,正是如此才会想要讨论一下
    liuzhaowei55
        8
    liuzhaowei55  
       2022-08-05 23:56:09 +08:00 via iPhone
    自己手写一个 validator 可以校验 enums ,然后如果用 jackson 可以使用 @jsonvalve 注解加在 enums 属性上来指明反序列化的字段
    oneisall8955
        9
    oneisall8955  
       2022-08-06 00:45:07 +08:00 via Android
    @daiwenzh5 每个人有每个人的理解,举个例子,搜索引擎枚举,前端传递 BAIDU,GOOGLE,SOUGOU ,比 0 ,1 ,2 更优雅。

    另外,技术上当然可以做自定义序列化反序列化,你想要的都可以,不过得区分 fastjson ,jackson ,gson 等 json 工具,因为哪天不知道某个同事用的工具不支持被吐槽
    daiwenzh5
        10
    daiwenzh5  
    OP
       2022-08-06 00:59:41 +08:00
    @oneisall8955 不是序列化的问题, 而是同时使用枚举入参,并且注解校验,目前我了解的是无法做到的,因为序列化在前,没有的值,就成了 null
    panxiuqing
        11
    panxiuqing  
       2022-08-06 07:20:09 +08:00 via Android
    如果用枚举类型接收,为什么要知道意外值?
    ymmud
        12
    ymmud  
       2022-08-06 09:03:59 +08:00
    在原始 class 上使用枚举,对外使用原始值。 json -> vo -> 原始 class
    oneisall8955
        13
    oneisall8955  
       2022-08-06 10:41:18 +08:00 via Android
    @daiwenzh5 那,直接在反序列化 throw ?不也能达到校验效果?
    tairan2006
        14
    tairan2006  
       2022-08-06 11:17:22 +08:00
    你直接用枚举接受,然后在字段上加一个 @NotNull 就行……
    mossrock
        15
    mossrock  
       2022-08-06 13:17:41 +08:00
    @JsonEnumDefaultValue
    UNKNOWN(-1, "未知");
    用这个?不确定是不是这个场景
    read_unknown_enum_values_using_default_value
    daiwenzh5
        16
    daiwenzh5  
    OP
       2022-08-06 17:41:15 +08:00
    @tairan2006 #14 NotNull 只是非空校验,如果允许为空呢?可以不填,但是填了必须在可选范围内的这种
    daiwenzh5
        17
    daiwenzh5  
    OP
       2022-08-06 17:43:11 +08:00
    @mossrock #15 这种的我考虑过,但是需要在枚举中手动设置一个“未知”枚举项了,如果做团队通用设计的话,通过人工约束也不太好,枚举又不能自定义抽象类,所以我在描述中也说了,测试了反射动态添加 UNKNOWN 枚举值。
    daiwenzh5
        18
    daiwenzh5  
    OP
       2022-08-06 17:48:37 +08:00
    @oneisall8955 #13 额,实际上对于单个入参异常是无所谓,但是对于批量的情况下,我是想要知道那些数据是正确的,哪些是错误的,此时异常的话就终止了,目前看来,好像是只有用 String, Interge 这种原始类型,去映射枚举的 name ,或者 code 比较好一点,用反射动态写入枚举值,感觉挺怪的。
    这个问题是最近在做 Excel 导入时想到的,想做成一个通用的自动校验。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1572 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 17:10 · PVG 01:10 · LAX 09:10 · JFK 12:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.