[英]Inferring String value type in Groovy
I have a situation where I will be given a String and I need to determine what Class<?>
best suits its value given the following constraints: 我有一种情况,我会得到一个字符串,我需要确定什么
Class<?>
最适合其值,给出以下约束:
"true"
or "false"
, it's a Boolean
"true"
或"false"
,则它是一个Boolean
Integer
Integer
,那么它就是一个Integer
Double
Double
YYYY-MM-DD hh:mm:ss.sss
, then its a Java Date
YYYY-MM-DD hh:mm:ss.sss
,那么它是一个Java Date
String
afterall String
毕竟 My best attempt is nasty and involves a lot of nested try/catch
blocks: 我最好的尝试是讨厌的,涉及很多嵌套的
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
}
Are there any Groovier ways of accomplishing this, perhaps something endemic to some obscure Groovy reflection API? 是否有任何Groovier方法来实现这一点,也许某些模糊的Groovy反射API特有的东西?
There are two methods which can help you in Groovy's extended String class (actually on CharSequence
): 在Groovy的扩展String类中有两种方法可以帮助你(实际上在
CharSequence
):
But for other cases, AFAIK, you are on your own to implement the parsing. 但对于其他情况,AFAIK,您可以自己实现解析。 You could try working with a map and some closures, to reduce some boilerplate:
您可以尝试使用地图和一些闭包,以减少一些样板:
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
Note that if (Double)
precedes (Integer)
the tests won't work, since 9
is both a double and a integer. 请注意,如果
(Double)
在(Integer)
(Double)
之前,则测试将不起作用,因为9
既是double又是整数。
Groovy has a few features that would allow you to make this logic groovier. Groovy有一些功能可以让你使这个逻辑更加流畅。
isInteger
and isDouble
built-in CharSequence methods from the Groovy JDK. isInteger
和isDouble
内置CharSequence方法。 Sadly, there's not a strict isBoolean
so we'll need to implement that ourselves. isBoolean
所以我们需要自己实现。 Combining these features... 结合这些功能......
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
I used a regex instead of SimpleDateFormat to avoid having to catch an Exception. 我使用正则表达式而不是SimpleDateFormat来避免必须捕获异常。 It probably has slightly difference semantics, but you could alternatively create a helper method that returns false if there's an Exception thrown by
Date.parse
. 它可能具有稍微不同的语义,但您可以创建一个辅助方法,如果
Date.parse
抛出异常,则返回false。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.