使用十进制分隔符的Grails数据绑定

使用十进制分隔符的Grails数据绑定,grails,Grails,当我使用grail自动数据绑定“ex:Test t=new Test(params)”和双表单字段上的十进制分隔符时,我遇到了一个问题。经过几次搜索,我发现它与浏览器的区域设置有关 例如: 如果我输入的数字以小数点“3.45”分隔,则不起作用(忽略数字的小数部分)。它在我的数据库中存储了3.0 如果我做同样的测试,但使用逗号'3,45'作为十进制分隔符,一切正常。Grails将3.45存储在数据库中 问题是没有人用逗号分隔符输入数字。(当设置为fr_CA时,即使是numpad也输入一个点“.”)

当我使用grail自动数据绑定“ex:Test t=new Test(params)”和双表单字段上的十进制分隔符时,我遇到了一个问题。经过几次搜索,我发现它与浏览器的区域设置有关

例如: 如果我输入的数字以小数点“3.45”分隔,则不起作用(忽略数字的小数部分)。它在我的数据库中存储了3.0

如果我做同样的测试,但使用逗号'3,45'作为十进制分隔符,一切正常。Grails将3.45存储在数据库中

问题是没有人用逗号分隔符输入数字。(当设置为fr_CA时,即使是numpad也输入一个点“.”)

我已经找到了一些解决方案,比如注册自定义数字编辑器(当你有很多应用程序时有点痛苦)或者将全局LocalResolver设置为en_US(最后一个解决方案不起作用,因为我失去了应用程序的所有国际化功能)

那么,有没有人有一个简单的解决方案来解决这个问题

使用: Grails:2.2.0 浏览器:谷歌浏览器


非常感谢

我已经搜索和尝试了两天。我最终选择定义一个自定义属性YeditorRegistar。这样,我就可以修复双字段格式的区域设置。但是,我不认为这是最好的解决方案,因为它将应用于我所有的双字段。但与此同时,这项工作做得相当好。因此,如果有人有更好的解决方案,我会很高兴测试它并更新我的代码

我就是这样设置的:

1-创建一个实现PropertyEditorRegistrar的新groovy类(如果您已经有了一个,只需将该方法包含的部分代码添加到现有类中)

2-在conf/spring/resources.goovy中定义定制注册器(当然,如果它还没有出现的话)

3-就是这样,Grails自动数据绑定将很好地工作

Test t = new Test(params); 
//params contains many Double fields with dot '.' as decimal delimiter
不要犹豫发布更好的解决方案。。。 谢谢

编辑1

由于Grails2.3,此解决方案不再有效。如果仍要使用此解决方案,则必须将此配置添加到Config.groovy文件中

grails.databinding.useSpringBinder=true

或者实现一个新的。我尝试了其中的一些,但似乎没有解决十进制定界符问题。谢谢你发布答案,如果你知道如何

编辑2

由于Grails2.4+版本,您可以定义自己的ValueConverter来绕过基本的语言环境验证。请注意,您必须删除在初始帖子和编辑1中所做的更改。以下是如何实现自定义ValueConverter:

conf/spring/resources.groovy

// Place your Spring DSL code here
beans = {
    "defaultGrailsjava.lang.DoubleConverter"(DoubleValueConverter)
}

class DoubleValueConverter implements ValueConverter {

    public LongValueConverter() {
    }

    boolean canConvert(value) {
        value instanceof Double
    }

    def convert(value) {
        //In my case returning the same value did the trick but you can define 
        //custom code that takes care about comma and point delimiter...
        return value
    }

    Class<?> getTargetType() {
        return Double.class
    }
}
//将您的Spring DSL代码放在这里
豆子={
“defaultGrailsjava.lang.DoubleConverter”(DoubleValueConverter)
}
类DoubleValueConverter实现ValueConverter{
公共价值转换器(){
}
布尔canConvert(值){
Double的值实例
}
def转换(值){
//在我的例子中,返回相同的值确实起了作用,但您可以定义
//关注逗号和点分隔符的自定义代码。。。
返回值
}
类getTargetType(){
返回双人舱
}
}

我这里也有同样的问题。例如,德国的用户通常会输入一个(逗号)作为十进制分隔符,但显然您不能阻止他输入点;)此外,如果从Javascript中填充值,则很难获得本地化的数字。所以我为控制器编写了这个小助手方法。它可能无法涵盖所有可能的场景,但我需要它来输入GPS坐标。请随时提出改进建议

    /**
     * Replaces , in the param with . an converts it to a Double.
     * @param paramName an array of paramater names
     */
    private convertDicimalParamsToDouble(paramName) {
        paramName.each { it
            def val = params[it]
            if(val) {
                val = val.replace(",", ".")
                try {
                    params[it] = Double.parseDouble(val)
                } catch (NumberFormatException) {
                    //ignore
                }
                log.debug("Converted decimal param ${it} with value '${params[it]}' to new value '${val}'")
            }
        }
    }
然后这样称呼它,例如:

def save() {        
    convertDicimalParamsToDouble(["lat", "lng"])
    ...

对于Grails2.3+,您可以正确地覆盖默认的活页夹/转换器,尽管它不是简单的或直观的


请参见我的回答:

我正在使用grails 3.3.1,而此解决方案不适用于我的命令对象。另外,@bingsing也不起作用。我不知道他们为什么要改变旧的行为。新的一个很恶心:/
    /**
     * Replaces , in the param with . an converts it to a Double.
     * @param paramName an array of paramater names
     */
    private convertDicimalParamsToDouble(paramName) {
        paramName.each { it
            def val = params[it]
            if(val) {
                val = val.replace(",", ".")
                try {
                    params[it] = Double.parseDouble(val)
                } catch (NumberFormatException) {
                    //ignore
                }
                log.debug("Converted decimal param ${it} with value '${params[it]}' to new value '${val}'")
            }
        }
    }
def save() {        
    convertDicimalParamsToDouble(["lat", "lng"])
    ...