Я перенес реализацию IBM ICU BigDecimal для клиента Actionscript. Кто-то еще опубликовал свою почти идентичную версию здесь как проект кода Google. Наша версия добавляет несколько удобных методов для сравнения.
Вы можете расширить конечную точку Blaze AMF, добавив поддержку сериализации для BigDecimal. Обратите внимание, что код в другом ответе кажется неполным, и по нашему опыту он не работает в производстве.
AMF3 предполагает, что дубликаты объектов, черты и строки отправляются по ссылке. Таблицы ссылок на объекты должны быть синхронизированы во время сериализации, иначе клиент потеряет синхронизацию этих таблиц во время десериализации и начнет выдавать ошибки приведения классов, или повреждать данные в полях, которые не совпадают, но приводятся нормально ...
Вот исправленный код:
public void writeObject(final Object o) throws IOException {
if (o instanceof BigDecimal) {
write(kObjectType);
if(!byReference(o)){ // if not previously sent
String s = ((BigDecimal)o).toString();
TraitsInfo ti = new TraitsInfo("java.math.BigDecimal",false,true,0);
writeObjectTraits(ti); // will send traits by reference
writeUTF(s);
writeObjectEnd(); // for your AmfTrace to be correctly indented
}
} else {
super.writeObject(o);
}
}
Существует еще один способ отправки типизированного объекта, который не требует Externalizable на клиенте. Клиент вместо этого установит свойство textValue для объекта:
TraitsInfo ti = new TraitsInfo("java.math.BigDecimal",false,false,1);
ti.addProperty("textValue");
writeObjectTraits(ti);
writeObjectProperty("textValue",s);
В любом случае вашему классу Actionscript понадобится этот тег:
[RemoteClass(alias="java.math.BigDecimal")]
Класс Actionscript также нуждается в текстовом свойстве, совпадающем с тем, которое вы выбрали для отправки, которое инициализирует значение BigDecimal, или, в случае объекта Externalizable, пару методов, подобных этому:
public function writeExternal(output:IDataOutput):void {
output.writeUTF(this.toString());
}
public function readExternal(input:IDataInput):void {
var s:String = input.readUTF();
setValueFromString(s);
}
Этот код касается только данных, передаваемых с сервера на клиент. Для десериализации в другом направлении от клиента к серверу мы решили расширить AbstractProxy и использовать класс-оболочку для временного хранения строкового значения BigDecimal до создания фактического объекта, поскольку вы не можете создать экземпляр BigDecimal, а затем присвойте значение, так как дизайн Blaze / LCDS предполагает, что это должно быть в случае со всеми объектами.
Вот прокси-объект, чтобы обойти обработку по умолчанию:
public class BigNumberProxy extends AbstractProxy {
public BigNumberProxy() {
this(null);
}
public BigNumberProxy(Object defaultInstance) {
super(defaultInstance);
this.setExternalizable(true);
if (defaultInstance != null)
alias = getClassName(defaultInstance);
}
protected String getClassName(Object instance) {
return((BigNumberWrapper)instance).getClassName();
}
public Object createInstance(String className) {
BigNumberWrapper w = new BigNumberWrapper();
w.setClassName(className);
return w;
}
public Object instanceComplete(Object instance) {
String desiredClassName = ((BigNumberWrapper)instance).getClassName();
if(desiredClassName.equals("java.math.BigDecimal"))
return new BigDecimal(((BigNumberWrapper)instance).stringValue);
return null;
}
public String getAlias(Object instance) {
return((BigNumberWrapper)instance).getClassName();
}
}
Этот оператор должен будет выполняться где-то в вашем приложении, чтобы связать прокси-объект с классом, которым вы хотите управлять. Мы используем статический метод:
PropertyProxyRegistry.getRegistry().register(
java.math.BigDecimal.class, new BigNumberProxy());
Наш класс-обёртка выглядит так:
public class BigNumberWrapper implements Externalizable {
String stringValue;
String className;
public void readExternal(ObjectInput arg0) throws IOException, ClassNotFoundException {
stringValue = arg0.readUTF();
}
public void writeExternal(ObjectOutput arg0) throws IOException {
arg0.writeUTF(stringValue);
}
public String getStringValue() {
return stringValue;
}
public void setStringValue(String stringValue) {
this.stringValue = stringValue;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}