[
https://issues.apache.org/jira/browse/FREEMARKER-232?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17944708#comment-17944708
]
Sune Keller commented on FREEMARKER-232:
----------------------------------------
If to take locale properly into account, I would probably do something like
this, though I am not sure if FreeMarker would require a thread-safe use of the
NumberFormat instance. This appears to correctly preserve the scale of the
BigDecimal:
{code:java}
private @NonNull Configuration getConfiguration() {
final var cfg = new Configuration(Configuration.VERSION_2_3_34);
cfg.setNumberFormat("@bob");
cfg.setCustomNumberFormats(Map.of("bob", new TemplateNumberFormatFactory() {
@Override
public TemplateNumberFormat get(String params, Locale locale,
Environment env) {
final var numberFormat = getNumberInstance(locale);
return new TemplateNumberFormat() {
@Override
public String formatToPlainText(TemplateNumberModel
numberModel) throws TemplateModelException, TemplateValueFormatException {
final var number = numberModel.getAsNumber();
if (number instanceof BigDecimal bigDecimal) {
numberFormat.setMinimumFractionDigits(bigDecimal.scale());
numberFormat.setMaximumFractionDigits(bigDecimal.scale());
return numberFormat.format(bigDecimal);
}
numberFormat.setMinimumFractionDigits(0);
numberFormat.setMaximumFractionDigits(Integer.MAX_VALUE);
return numberFormat.format(number);
}
@Override
public boolean isLocaleBound() {
return true;
}
@Override
public String getDescription() {
return "big decimal formatting template number format";
}
};
}
}));
return cfg;
} {code}
> Add configuration option to skip call to stripTrailingZeros on BigDecimal
> Numbers
> ---------------------------------------------------------------------------------
>
> Key: FREEMARKER-232
> URL: https://issues.apache.org/jira/browse/FREEMARKER-232
> Project: Apache Freemarker
> Issue Type: Improvement
> Components: engine
> Affects Versions: 2.3.32
> Reporter: Sune Keller
> Priority: Major
>
> When evaluating a template in which the model contains a field for which the
> value is a simple BigDecimal with a given scale and trailing zeros within
> that scale, the trailing zeros are stripped away by the implementation in
> {{{}freemarker.core.CTemplateNumberFormat#formatToPlainText{}}}:
> {code:java}
> } else if (num instanceof BigDecimal) {
> BigDecimal bd = ((BigDecimal) num).stripTrailingZeros();
> int scale = bd.scale();
> if (scale <= 0) {
> // A whole number. Maybe a long ID in a database or other system, and
> for those exponential form is not
> // expected generally, so we avoid that. But then, it becomes too
> easy to write something like
> // 1e1000000000000 and kill the server with a terra byte long
> rendering of the number, so for lengths
> // that realistically aren't ID-s or such, we use exponential format
> after all:
> if (scale <= -100) {
> return bd.toString(); // Will give exponential form for this scale
> }
> return bd.toPlainString(); // Never gives exponential form
> }
> // `db` is not a whole number. Note that `bd` is already normalized to
> not have trailing zeroes.
> return bd.toString(); // Gives exponential form of the absolute value of
> the number is less than 1E-7 {code}
> It would be wonderful to be able to configure whether any trailing zeros are
> stripped or not by way of some configuration option, so as to avoid having to
> copy and re-implement this final non-public class.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)