当我在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)
非常感谢!
答案 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"])
...