我有以下代码:
xwork-conversion.properties
java.math.BigDecimal=demo.BigDecimalConverter
BigDecimalConverter.java
package demo;
import java.math.BigDecimal;
import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;
public class BigDecimalConverter extends StrutsTypeConverter{
@Override
public Object convertFromString(Map context, String[] values, Class clazz) {
System.out.println("BigDecimal : Converting from String : " + values[0]);
return new BigDecimal(values[0]);
}
@Override
public String convertToString(Map context, Object value) {
String str = ((BigDecimal)value).toPlainString();
System.out.println("BigDecimal : Converted to String : " + str);
return str;
}
}
TheAction.java
package demo;
//imports...
public class TheAction extends ActionSupport {
private BigDecimal bigField; //with getter and setter
public String execute() {
return SUCCESS;
}
}
struts.xml
<package name="demo" extends="json-default">
<action name="processBig" class="demo.TheAction">
<result type="json"/>
</action>
</package>
观察
当提交请求时带有一些大的小数,比如 "12345678901234567890.123456789123456789"
,方法 convertFromString
被执行,值被转换为字符串并打印
BigDecimal : Converting from String : 12345678901234567890.123456789123456789
但是当解析响应时,方法 convertToString
不会被执行,因为它不会在标准输出上记录预期的行。 Struts2 在内部将 BigDecimal
转换为 String
并返回以下响应。
{"bigField":12345678901234567890.123456789123456789}
当在 JavaScript 中收到响应时,它变成了 12345678901234567000
,这是一个很大的值(value)损失。
问题:
- 为什么
BigDecimalConverter.convertToString
没有被调用? - 是否有任何其他方法可以实现此目的(无需定义相应的
String
字段和/或String
getter)?
请您参考如下方法:
解决它的一些可能的解决方案。
使用伪getter
public String getBigFieldString() {
return bigField != null ? bigField.toPlainString : null;
}
插件会将其序列化为 bigFieldString:"12345678901234567890.123456789123456789"
。您也可以使用字段的 getter 来执行此操作。
更改 JSON 插件代码 将 JSON 插件中的 org.apache.struts2.json.JSONWriter
类复制到您的项目代码中。并更新 process
方法如下。 (这样做时要小心。)
package org.apache.struts2.json;
...
class JSONWriter {
...
private void process(Object object, Method method) throws JSONException {
this.stack.push(object);
if (object instanceof Class) {
this.string(object);
} else if (object instanceof Boolean) {
this.bool((Boolean) object);
}
// Begin: Handling of Big Decimal, Keep this code above Handling of Number
else if (object instanceof BigDecimal) {
this.string(((BigDecimal)object).toPlainString());
}
// End: Handling of Big Decimal
else if (object instanceof Number) {
this.add(object);
} else if (object instanceof String) {
this.string(object);
} else if (object instanceof Character) {
this.string(object);
} else if (object instanceof Map) {
this.map((Map) object, method);
} else if (object.getClass().isArray()) {
this.array(object, method);
} else if (object instanceof Iterable) {
this.array(((Iterable) object).iterator(), method);
} else if (object instanceof Date) {
this.date((Date) object, method);
} else if (object instanceof Calendar) {
this.date(((Calendar) object).getTime(), method);
} else if (object instanceof Locale) {
this.string(object);
} else if (object instanceof Enum) {
this.enumeration((Enum) object);
} else {
this.bean(object);
}
this.stack.pop();
}
...
}