Domanda

I have the following code:

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>

Observation

When request is submitted with some big decimal say "12345678901234567890.123456789123456789", method convertFromString is executed and value is converted to string and prints

BigDecimal : Converting from String : 12345678901234567890.123456789123456789

But when response is parsed, method convertToString is not executed as it does not log expected line on standard output. Struts2 internally converts BigDecimal to String and following response is returned.

{"bigField":12345678901234567890.123456789123456789}

When response is received in JavaScript, it becomes 12345678901234567000, a big loss of value.


Questions:

  • Why BigDecimalConverter.convertToString is not being called?
  • Is there any other way to achieve this (without defining corresponding String field and/or String getter)?
È stato utile?

Soluzione 2

Short answer:

  1. BigDecimalConverter.convertToString is not being called because it isn't used.

    Is there any other way to achieve this (without defining corresponding String field and/or String getter)?

  2. No, you can't. JavaScript is a not your language choice or you can use it as string. Means that a limitation of the language you can overcome with something like bigdecimal.js.

Altri suggerimenti

Some possible solutions to resolve it.

Use a pseudo getter

public String getBigFieldString() {
    return bigField != null ? bigField.toPlainString : null;
}

and plugin will serialize it as bigFieldString:"12345678901234567890.123456789123456789". You can also use field's getter to do this.


Change JSON Plugin Code Copy org.apache.struts2.json.JSONWriter class from JSON Plugin to your project code. and update process method as below. (Be careful while doing this.)

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();
    }
    ...
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top