Reputation: 5
How can I check if a string can be converted to a number?
For example this will not work unless SelfAge
is a valid String to convert:
<#if SelfAge?? && (SelfAge?number > 15)>
Test Data:
SelfAge = "October 30, 1913 // "Can't convert this string to number: "October 30, 1913"
SelfAge = "User-submitted-comment" // Can't convert this string to number: "User-submitted-comment"
SelfAge = "1/12" // Can't convert this string to number: "1/12"
Upvotes: 0
Views: 3104
Reputation: 91
This works for non-negative integers:
[#if ageString?matches("^\\d+$")]
[#assign ageNumber = ageString?number]
[/#if]
Upvotes: 2
Reputation: 684
There are 2 appraoches:
Assuming the input can be one of the following
<#assign SelfAge = "October 30, 1913" >
<#assign SelfAge = "1/12" >
<#assign SelfAge = "101" >
<#assign SelfAge = "User-submitted-comment" >
You can do this (starting from 2.3.3) using attempt, recover:
<#attempt>
<#-- try -->
<#if SelfAge?? && (SelfAge?number > 15)>
Will do something with the number
</#if>
<#recover>
<#-- catch -->
Can't convert this string to number: ${SelfAge}
</#attempt>
However, this solution has limitations:
This leads us to the second and better approach.
You can use TemplateHashModel Hash to create a model of a utility class of your own that you can use to access more customized funcaitonalities that Freemarker doesn't provide off the bat.
Our goal is to create a method named isNumber
inside a class in your project called MyUtils
then we will use this method to check the string and get eaither true or false. In this manner:
<#if Utils.isNumber(SelfAge)>
First, create your MyUtils
class:
package example;
public class MyUtils {
public static boolean isNumber(String s){
try {
Integer.parseInt(s);
return true;
}
catch (NumberFormatException e){
return false;
}
}
}
Second, implement a bean wrapper to create static models container and add your class to it (make sure package path is correct):
BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
TemplateHashModel staticModels = wrapper.getStaticModels();
TemplateHashModel myUtilsWrapper = (TemplateHashModel) staticModels.get( "example.MyUtils" );
If your application is Spring app, the wrapper can be added to the controller redirecting to your page, here is my controller class:
import freemarker.ext.beans.BeansWrapper;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateModelException;
@RestController
public class HelloController {
@RequestMapping("/")
public ModelAndView hello() throws TemplateModelException {
ModelAndView mainView = new ModelAndView();
mainView.setViewName("index");
BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
TemplateHashModel staticModels = wrapper.getStaticModels();
TemplateHashModel myUtilsWrapper = (TemplateHashModel) staticModels.get( "example.MyUtils" );
mainView.getModel().put("Utils", myUtilsWrapper);
return mainView;
}
}
Notice how we named our wrapper: Utils
<-- this is the name we will use to access method from Freemarker template.
Now in Freemarker do this:
<#if Utils.isNumber(SelfAge)>
<div>Will do something with the number</div>
<#else>
<div>Can't convert this string to number: ${SelfAge}</div>
</#if>
It will produce same output as first approach, with better code encapsulation.
I'd go one further step and implement the checker method using Apache Commons NumberUtils.isCreatable()
This way nulls, negative/postive signs, and all number formats will be covered!
public static boolean isNumeric(String s){
return NumberUtils.isCreatable(s);
}
Then in Freemarker:
<#if Utils.isNumeric(SelfAge)>
<div>Will do something with the number</div>
<#else>
<div>Can't convert this string to number: ${SelfAge}</div>
</#if>
Example:
This case <#assign SelfAge = "-101.1" >
will fail in first and second appraoch but will work in the Bonus suggestion:
Will do something with the number
Upvotes: 2