繁体   English   中英

在Groovy中推断字符串值类型

[英]Inferring String value type in Groovy

我有一种情况,我会得到一个字符串,我需要确定什么Class<?>最适合其值,给出以下约束:

  • 如果String(忽略大小写)等于"true""false" ,则它是一个Boolean
  • 否则,如果String是一个没有小数点的Integer ,那么它就是一个Integer
  • 否则,如果String是一个数字,那么它就是一个Double
  • 否则,如果String匹配日期时间格式YYYY-MM-DD hh:mm:ss.sss ,那么它是一个Java Date
  • 否则它只是一个String毕竟

我最好的尝试是讨厌的,涉及很多嵌套的try/catch块:

// Groovy pseudo-code
Class<?> determineValueType(String value) {
    Class<?> clazz
    if(value.equalsIgnoreCase('true') || value.equalsIgnoreCase('false')) {
        clazz = Boolean
    } else {
        try {
            Integer.parse(value)
            clazz = Integer
        } catch(Exception ex1) {
            try {
                Double.parse(value)
                clazz = Double
            } catch(Exception ex2) {
                try {
                    Date.parse('YYYY-MM-DD hh:mm:ss.sss', value)
                    clazz = Date
                } catch(Exception ex3) {
                    clazz = String
                }
            }
        }
    }

    clazz
}

是否有任何Groovier方法来实现这一点,也许某些模糊的Groovy反射API特有的东西?

在Groovy的扩展String类中有两种方法可以帮助你(实际上在CharSequence ):

但对于其他情况,AFAIK,您可以自己实现解析。 您可以尝试使用地图和一些闭包,以减少一些样板:

Class parse(val) {
    def convert = [
        (Integer) : { it.toInteger() },
        (Double)  : { it.toDouble() },
        (Date)    : { Date.parse('YYYY-MM-DD hh:mm:ss.sss', it) },
        (Boolean) : { Boolean.parseBoolean it },
        (String)  : { it }
    ]

    convert.findResult { key, value ->
        try {
            if (value(val)) return key
        } catch (e) {}
    }
}

assert parse('9.1') == Double
assert parse('9') == Integer
assert parse('1985-10-26 01:22:00.000') == Date // great scott!
assert parse('chicken') == String
assert parse('True') == Boolean

请注意,如果(Double)(Integer) (Double)之前,则测试将不起作用,因为9既是double又是整数。

Groovy有一些功能可以让你使这个逻辑更加流畅。

  1. 强大的switch语句,支持正则表达式和闭包。
  2. Groovy JDK中的isIntegerisDouble内置CharSequence方法。 可悲的是,没有严格的isBoolean所以我们需要自己实现。
  3. 安全导航操作员避免NPE。

结合这些功能......

Class<?> determineValueType(String value) {
    switch (value) {
        case { ['true', 'false'].contains(value?.toLowerCase()) }: 
            return Boolean
        case { value?.isInteger() }: 
            return Integer
        case { value?.isDouble() }: 
            return Double
        case ~/^\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2}\.\d{3}$/: 
            return Date
        default: 
            return String
    }
}

assert determineValueType('true') == Boolean
assert determineValueType('false') == Boolean
assert determineValueType('2039230') == Integer
assert determineValueType('203923.0') == Double
assert determineValueType('2016-07-26 12:00:00.000') == Date
assert determineValueType('foo') == String

我使用正则表达式而不是SimpleDateFormat来避免必须捕获异常。 它可能具有稍微不同的语义,但您可以创建一个辅助方法,如果Date.parse抛出异常,则返回false。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM