Java freemarker模板中宏的递归类型检查
我想递归遍历LinkedHashMap的键和值,并使用ApacheFreeMarker将它们打印到模板中。 LinkedHashMap包含作为字符串的键和作为对象的值。这些值可以是LinkedHashMap、ArrayList或字符串 下面的java源代码返回我想使用freemarker创建的字符串Java freemarker模板中宏的递归类型检查,java,recursion,freemarker,typechecking,Java,Recursion,Freemarker,Typechecking,我想递归遍历LinkedHashMap的键和值,并使用ApacheFreeMarker将它们打印到模板中。 LinkedHashMap包含作为字符串的键和作为对象的值。这些值可以是LinkedHashMap、ArrayList或字符串 下面的java源代码返回我想使用freemarker创建的字符串 private String printLinkedHashMap(LinkedHashMap<?, ?> map, int counter) { if(map == n
private String printLinkedHashMap(LinkedHashMap<?, ?> map, int counter) {
if(map == null) {
return "";
}
StringBuilder sb = new StringBuilder();
Set<?> set = map.entrySet();
sb.append(getSpaces(counter) + "<ul>\n");
for (Object object : set) {
if(object instanceof Entry<?, ?>) {
Entry<?, ?> entry = (Entry<?, ?>) object;
sb.append(getSpaces(counter) + "<li>" + entry.getKey() + " = ");
if(entry.getValue() instanceof LinkedHashMap<?, ?>) {
sb.append("</li>\n" + printLinkedHashMap((LinkedHashMap<?, ?>) entry.getValue(), counter+1));
} else if(entry.getValue() instanceof ArrayList<?>){
ArrayList<?> listOfValues = (ArrayList<?>) entry.getValue();
sb.append("</li>" + printArrayList(listOfValues, counter+1));
} else {
sb.append(entry.getValue().toString() + "</li>\n");
}
}
}
sb.append(getSpaces(counter) + "</ul>\n");
return sb.toString();
}
private String printArrayList(ArrayList<?> listOfValues, int counter) {
StringBuilder sb = new StringBuilder();
if(listOfValues.size() > 1) {
for (int i = 0; i < listOfValues.size(); i++) {
sb.append('\n' + getSpaces(counter));
sb.append("<li>" + listOfValues.get(i).toString() + "</li>");
}
} else {
sb.append(listOfValues.get(0).toString());
}
return sb.toString();
}
私有字符串printLinkedHashMap(LinkedHashMap映射,int计数器){
if(map==null){
返回“”;
}
StringBuilder sb=新的StringBuilder();
Set=map.entrySet();
sb.append(getSpaces(counter)+“\n”);
用于(对象:集){
if(条目的对象实例){
条目=(条目)对象;
sb.append(getSpaces(counter)+“- ”+entry.getKey()+”=”);
if(LinkedHashMap的entry.getValue()实例){
sb.append(“
\n”+printLinkedHashMap((LinkedHashMap)entry.getValue(),counter+1));
}else if(entry.getValue()instanceof ArrayList){
ArrayList listOfValues=(ArrayList)entry.getValue();
sb.追加(“”+printArrayList(值列表,计数器+1));
}否则{
sb.append(entry.getValue().toString()+“\n”);
}
}
}
sb.append(getSpaces(counter)+“
\n”);
使某人返回字符串();
}
私有字符串printArrayList(ArrayList listOfValues,int计数器){
StringBuilder sb=新的StringBuilder();
if(listOfValues.size()>1){
对于(int i=0;i”+listOfValues.get(i).toString()+””);
}
}否则{
sb.append(listOfValues.get(0.toString());
}
使某人返回字符串();
}
输出为:
<ul>
<li>defaultVar = </li>
<ul>
<li>subdefaultVar = </li>
<ul>
<li>subsubdefaultVar = defaultValue</li>
<li>subsubdefaultVariable = defaultValue2</li>
</ul>
<li>anothersubdefaultVar = </li>
<ul>
<li>anothersubsubdefaultVar = anotherdefaultValue</li>
<li>anothersubsubdefaultVariable = anotherdefaultValue2</li>
</ul>
</ul>
<li>defaultVariable = Defaultshort</li>
</ul>
- defaultVar=
- subdefaultVar=
- subsubdefaultVar=defaultValue
- subsubdefaultVariable=defaultValue2
- 另一个SubDefaultVar=
- AnotherSubDefaultVar=anotherdefaultValue
- AnotherSubDefaultVariable=anotherdefaultValue2
- defaultVariable=Defaultshort
freemarker模板包含以下部分
<#list map.entrySet() as entry>
<@printLinkedHashMap entry/>
<#macro printLinkedHashMap obj>
<#if obj??>
<ul>
<#if obj.key??>
<#if obj.key?is_string>
<li>${obj.key} =
</#if>
</#if>
<#if obj.value??>
<#if obj.value?is_hash_ex>
</li>
<#list obj.value.entrySet() as entry>
<@printLinkedHashMap entry/>
</#list>
<#elseif obj.value?is_collection>
</li>
<ul>
<#list obj.value as current>
<li>${current.value}</li>
</#list>
</ul>
<#elseif obj.value?is_string>
${obj.value}</li>
</#if>
</#if>
</ul>
</#if>
</#macro>
</#list>
- ${obj.key}=
- ${current.value}
${obj.value}
使用此模板时,将显示以下错误:
The following has evaluated to null or missing:
==> obj.value.entrySet [in template "template.ftl" at line 55, column 26]
----
Tip: It's the step after the last dot that caused this error, not those before it.
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----
----
FTL stack trace ("~" means nesting-related):
- Failed at: #list obj.value.entrySet() as entry [in template "template.ftl" in macro "printLinkedHashMap" at line 55, column 19]
- Reached through: @printLinkedHashMap entry [in template "template.ftl" in macro "printLinkedHashMap" at line 56, column 21]
- Reached through: @printLinkedHashMap entry [in template "template.ftl" in macro "printLinkedHashMap" at line 56, column 21]
- Reached through: @printLinkedHashMap entry [in template "template.ftl" at line 41, column 11]
----
以下内容的计算结果为空或缺失:
==>obj.value.entrySet[在第55行第26列的模板“template.ftl”中]
----
提示:导致此错误的是最后一个点之后的步骤,而不是之前的步骤。
----
提示:如果已知失败的表达式在法律上引用了有时为null或缺少的内容,请指定一个默认值,如myOptionalVar!myDefault,或在出现时使用缺少时使用。(这些仅包括表达式的最后一步;要覆盖整个表达式,请使用括号:(myOptionalVar.foo)!myDefault,(myOptionalVar.foo)??
----
----
FTL堆栈跟踪(“~”表示嵌套相关):
-在以下位置失败:#将obj.value.entrySet()列为条目[在第55行第19列的宏“printLinkedHashMap”的模板“template.ftl”中]
-通过:@printLinkedHashMap条目[在第56行第21列的宏“printLinkedHashMap”的模板“template.ftl”中]
-通过:@printLinkedHashMap条目[在第56行第21列的宏“printLinkedHashMap”的模板“template.ftl”中]
-通过:@printLinkedHashMap条目[在模板“template.ftl”第41行第11列中]
----
错误显示“obj.value.entrySet()”似乎为空。但我不明白为什么会发生这种情况,以及如何修复这种情况
解决方案我为该问题创建了解决方案。如果其他人需要,我的ftl文件现在包含以下宏:
<#macro printLinkedHashMap entry>
<#if entry.key??>
<ul>
<#if entry.key??>
<#if entry.key?is_string>
<li>${entry.key} =
</#if>
</#if>
<#if entry.value??>
<#if entry.value?is_hash_ex>
<#if (entry.value.entrySet())??>
<#list entry.value.entrySet() as newEntry>
<#if newEntry.key??>
<#if newEntry.value??>
<@printLinkedHashMap newEntry/>
</#if>
</#if>
</#list>
<#elseif entry.value?is_collection>
<ul>
<#list entry.value as currentValue>
<li>currentValue</li>
</#list>
</ul>
<#else>
${entry.value}</li>
</#if>
</li>
</#if>
</#if>
</ul>
</#if>
</#macro>
- ${entry.key}=
- 当前值
${entry.value}
最可能的原因是,在您的结构中的某个地方有一个HashMap
,而不是LinkedHashMap
HashMap
被freemarker包装成一个SimpleHash
,它没有entrySet()
方法,导致错误obj.value.entrySet的计算结果为null或缺少
请注意,您应该更喜欢使用map?键
在地图上迭代。它将在HashMap
和LinkedHashMap
上工作(并按LinkedHashMap
的正确顺序返回键).最可能的原因是,在您的结构中某处存在一个HashMap
,而不是LinkedHashMap
HashMap
被freemarker包装成一个SimpleHash
,它没有entrySet()
方法,导致错误obj.value.entrySet的计算结果为null或缺少
请注意,您应该更喜欢使用map?键
在您的映射上进行迭代。这将在HashMap上都起作用<