[ 
https://issues.apache.org/jira/browse/FREEMARKER-232?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17944654#comment-17944654
 ] 

Sune Keller commented on FREEMARKER-232:
----------------------------------------

Well, yes, something like that. In my use case, I am processing externally 
configured templates with dynamic input values generated by yet another system, 
where the source of the input values knows the correct number of decimal places 
of any BigDecimal values provided, and the template authors do not necessarily 
know the correct scale ahead of time.

I do not propose to make this the default, but it would be very helpful to be 
able to avoid a workaround like this (assume this is in a Spring Boot 
application regarding the ObjectMapper bean):
{code:java}
private final ObjectMapper objectMapper;

@Autowired
void configureObjectMapper(ObjectMapper objectMapper) {
    objectMapper.configure(JsonNodeFeature.STRIP_TRAILING_BIGDECIMAL_ZEROES, 
false);
    objectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
}

...

private @NonNull Configuration getConfiguration() {
    final var cfg = new Configuration(Configuration.VERSION_2_3_34);
    cfg.setCustomNumberFormats(Map.of("number", new 
TemplateNumberFormatFactory() {
        @Override
        public TemplateNumberFormat get(String params, Locale locale, 
Environment env) {
            final var objectMapperForLocale = 
FreemarkerEvaluator.this.objectMapper.copy().setLocale(locale);
            return new TemplateNumberFormat() {
                @Override
                public String formatToPlainText(TemplateNumberModel 
numberModel) throws TemplateModelException, TemplateValueFormatException {
                    if (numberModel.getAsNumber() instanceof BigDecimal 
bigDecimal) {
                        try {
                            return 
objectMapperForLocale.writeValueAsString(bigDecimal);
                        } catch (JsonProcessingException ignored) {
                            return 
formatToPlainTextUsingCTemplateNumberFormat(numberModel);
                        }
                    }
                    return 
formatToPlainTextUsingCTemplateNumberFormat(numberModel);
                }

                private String 
formatToPlainTextUsingCTemplateNumberFormat(TemplateNumberModel numberModel) 
throws TemplateValueFormatException, TemplateModelException {
                    return 
env.getCTemplateNumberFormat().formatToPlainText(numberModel);
                }

                @Override
                public boolean isLocaleBound() {
                    return true;
                }

                @Override
                public String getDescription() {
                    return "big decimal formatting template number format";
                }
            };
        }
    }));
    cfg.setNumberFormat("@number");
    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)

Reply via email to