جافا - محول BigDecimal في Struts2 لا يقوم بالتحويل إلى سلسلة


لدي الكود التالي:

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، وهو خسارة كبيرة في القيمة.

الأسئلة:

  • لماذا لا يتم استدعاء BigDecimalConverter.convertToString؟
  • هل هناك طريقة أخرى لتحقيق هذا (دون تعريف حقل String المقابل و/أو دالة الحصول String)؟

الإجابة رقم 1

بعض الحلول الممكنة لحلها.

استخدم مستخلص زائف

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

وسيقوم الإضافة بتسلسلها كـ bigFieldString:"12345678901234567890.123456789123456789". يمكنك أيضًا استخدام دالة الحصول على الحقل للقيام بذلك.

تغيير كود ملحق JSON انسخ فئة org.apache.struts2.json.JSONWriter من ملحق JSON إلى كود مشروعك. وقم بتحديث طريقة 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();
    }
    ...
}

الإجابة رقم 2

إجابة قصيرة:

  1. BigDecimalConverter.convertToString لا يتم استدعاؤه لأنه غير مستخدم.

    هل هناك أي طريقة أخرى لتحقيق ذلك (دون تعريف حقل String المقابل و/أو دالة الحصول على String)؟

  2. لا، لا يمكنك. جافاسكريبت ليست خيار لغتك أو يمكنك استخدامها كسلسلة. هذا يعني أن هناك محدودية في اللغة يمكنك التغلب عليها باستخدام شيء مثل bigdecimal.js.