带小数分隔符的Grails数据绑定

时间:2013-02-14 14:56:54

标签: grails

当我在Double form字段上使用带有小数分隔符的grail自​​动数据绑定“ex:Test t = new Test(params)”时,我遇到了问题。经过几次搜索,我发现它与浏览器Locale有关。

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

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

问题是没有人用逗号分隔符输入数字。 (当设置为fr_CA时,甚至小键盘输入一个点'。'

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

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

使用: Grails:2.2.0 浏览器:Google Chrome(区域设置fr_CA)

非常感谢!

3 个答案:

答案 0 :(得分:16)

我一直在寻找和尝试2天。我最终选择定义一个自定义的PropertyEditorRegistar。这样,我只能为Double字段格式修复Locale。但是,我不认为它是最好的解决方案,因为它将应用于我的所有Double字段。但与此同时,它的工作做得很好。因此,如果某人有更好的解决方案,我将很乐意对其进行测试并更新我的代码。

所以我就是这样设置的:

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

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.propertyeditors.CustomNumberEditor;

public class CustomDoubleRegistrar implements PropertyEditorRegistrar {

    @Override
    public void registerCustomEditors(PropertyEditorRegistry registry) {
            //define new Double format with hardcoded Locale.ENGLISH
        registry.registerCustomEditor(Double.class, 
                 new CustomNumberEditor(Double.class, 
                           DecimalFormat.getInstance(Locale.ENGLISH),true))
    }

}

2-将自定义注册商定义到conf / spring / resources.goovy(如果它当然不在那里)

beans = {
    customPropertyEditorRegistrar(CustomDoubleRegistrar)
}

3-就是这样,Grails自动数据绑定工作正常

Test t = new Test(params); 
//params contains many Double fields with dot '.' as decimal delimiter

不要犹豫,发布更好的解决方案...... 感谢

编辑1

自Grails 2.3以来,此解决方案已不再有效。如果您仍想使用此解决方案,则必须将此配置添加到 Config.groovy 文件

grails.databinding.useSpringBinder = true

或实施新的DataBinding之一。我已经尝试了很少,但似乎没有解决小数分隔符问题。如果你知道怎么做,谢谢你发帖回答......

编辑2

从Grails 2.4+开始,您可以定义自己的ValueConverter以绕过基本的Locale验证。请注意您必须删除在初始帖子和编辑1 中所做的更改。以下是如何实现自定义ValueConverter:

<强> CONF /弹簧/ 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
    }
}

答案 1 :(得分:1)

对于Grails 2.3+,您可以正确覆盖默认的活页夹/转换器,尽管它不是微不足道或直观的。

请在此处查看我的回答:Binding real number values to Grails domain attributes (values sent by Dojo widgets)

答案 2 :(得分:0)

我在这里遇到同样的问题。例如,德国的用户通常会输入一个(逗号)作为小数分隔符,但显然你不能阻止他输入一个点;)另外,如果你从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"])
    ...