为什么 FreeMarkers 内置“?is_string”return 对一个对象为真?

Why does FreeMarkers built-in "?is_string" return true for an Object?

如果我将一个对象传递到模型中并使用内置的“?is_string”对其进行测试,它将错误地 return 一个真值。 是否可以(不检查 class 名称)对对象进行适当的类型检查?

FreeMarker: 2.3.28

重现代码:

public class Test {} 

// In Test Controller
ModelAndView mv = new ModelAndView("test");
mv.addObject("test", new Test());

// In test.ftl
<#if test?is_string>
  ${test} - is a string!
</#if>

// Result
Test@455b31c - is a string

问题是 FreeMarker 并不真正支持这种方法。 Java 对象通过 Configuration.objectWrapper 映射到某些模板语言值,模板只能看到该映射的结果。此外,模板语言有一个不同于 Java 的类型系统,一个简单的类型系统,没有 类。 (当时的设计目标是数据模型只是一些简单的树,无论后面有什么对象,模板都可以工作,只要它仍然提供相同的树。)?is_... 不检查 Java 类型,但类型根据模板语言。与通常的 ObjectWrapper-s 一样,一个 "generic" 对象(意思是,没有像 ListMapDate 等那样被识别的对象)可以用作字符串其值为 toString() returns,就模板语言而言,它是一个字符串。这是一种鸭子类型...

我能想到的解决方法是首先使用 ?is_hash 检查值,因为这将捕获所述通用对象(因为它们支持 .,它们也是散列,而不仅仅是字符串)。或者只是检查您希望出现在 Test 中的 属性。然后在 "else" 分支上你可以继续 ?is_string.