freemarker中将object转换为json

为了兼顾SEO和前后端分离开发实践,仍然选用freemarker模板制作主要页面入口文件。比较蛋疼的是,比较通用的元数据一般是塞在模板的model中的,页面上需要使用freemarker语法通过字符串拼接的方式转换为需要的js变量挂到页面上来。每一次一不小心就会犯下错误。于是乎,俺就狠下心写一个freemarker模板的自定义function,直接将model中的object对象转换为json对象。虽然目前还不是很完善,许多类型都没有判断,但是已经很好用了。

freemarker中将object转换为json

自定义函数

freemarker模板是支持自定义函数的,其格式如下:

1
2
3
4
5
<#function name param1 param2 … paramN>
<#return returnValue>
</#function>

其中 name 是函数名,param是传入的自定义参数,可以是多个参数。最后有个返回值即可。示例:

1
2
3
4
5
<#function avg x y>
<#return (x + y) / 2>
</#function>
用法:
${avg(10, 20)}

废话话不多说,object2json 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<#– 将ftl中的对象转换成json,只转换hash 和 数组 类型数据–>
<#function objectToJsonFunction object>
<#if object?is_enumerable>
<#local json = “[“>
<#list object as item>
<#if item?is_number >
<#local json = json + ‘${item}’>
<#if item_has_next>
<#local json = json + ‘,’>
</#if>
<#elseif item?is_string>
<#local json = json + ‘”${item?html!””?js_string}”‘>
<#if item_has_next>
<#local json = json + ‘,’>
</#if>
<#elseif item?is_boolean >
<#local json = json + ‘${item?string(“true”, “false”)}’>
<#if item_has_next>
<#local json = json + ‘,’>
</#if>
<#elseif item?is_enumerable>
<#local json = json + objectToJsonFunction(object[key])>
<#if item_has_next>
<#local json = json + ‘,’>
</#if>
<#elseif item?is_hash>
<#local json = json + objectToJsonFunction(object[key])>
<#if item_has_next>
<#local json = json + ‘,’>
</#if>
</#if>
</#list>
<#return json + “]”>
<#elseif object?is_hash || object?is_hash_ex>
<#local json = “{“>
<#assign keys = object?keys>
<#list keys as key>
<#if object[key]?is_number>
<#local json = json + ‘”${key}”: ${object[key]}’>
<#if key_has_next>
<#local json = json +’,’ >
</#if>
<#elseif object[key]?is_string>
<#local json = json + ‘”${key}”: “${object[key]?html!””?js_string}”‘>
<#if key_has_next>
<#local json = json +’,’ >
</#if>
<#elseif object[key]?is_boolean >
<#local json = json + ‘”${key}”: ${object[key]?string(“true”, “false”)}’>
<#if key_has_next>
<#local json = json +’,’ >
</#if>
<#elseif object[key]?is_enumerable>
<#local json = json + ‘”${key}”:’+ objectToJsonFunction(object[key])>
<#if key_has_next>
<#local json = json +’,’ >
</#if>
</#if>
</#list>
<#return json +”}”>
</#if>
</#function>

目前仅仅可以转换 hash对象、数组对象和常用的string,number,boolean 等数据类型,其他的有待补充,目前是忽略不处理。
写的比较简单,只是用到了freemarker中的一些语法,于是乎附上参考资料:

  1. freemarker手册
  2. 参考1,仅此足矣!
    ###坑的地方

后端直接在controller中塞了一个累的对象,这时候挂了,好遗憾。由于联调比较麻烦,费劲力气最后发现,竟然
对象上的一些方法也会进入函数中,而且都是可枚举的。 is_enumerable判断中出现问题了,java对象的方法
is_enumerable结果都为true,导致进入了循环体。最后解决方法是:

1
2
3
4
<#elseif object[key]?is_enumerable && !(object[key]?is_method) >
<#local json = json + ‘”${key}”:’+ objectToJsonFunction(object[key])>
<#if key_has_next>
<#local json = json +’,’ >

新的更新:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<#– 将ftl中的对象转换成json,只转换hash 和 数组 类型数据–>
<#– 注意有个坑就是 string?is_hash 也是 true –>
<#– item.class.simpleName == ‘Boolean’ 相当于 item?is_boolean–>
<#function objectToJsonFunction object>
<#if object??>
<#if object?is_enumerable>
<#local json = ‘[‘>
<#list object as item>
<#if item?is_number >
<#if item_index &gt; 0 && json != “[” >
<#local json = json +’,’ >
</#if>
<#local json = json + ‘${item}’>
<#elseif item?is_string>
<#if item_index &gt; 0 && json != “[” >
<#local json = json +’,’ >
</#if>
<#local json = json + ‘”${item?html!””?js_string}”‘>
<#elseif item?is_boolean >
<#if item_index &gt; 0 && json != “[” >
<#local json = json +’,’ >
</#if>
<#local json = json + ‘${item?string(“true”, “false”)}’>
<#elseif item?is_enumerable && !(item?is_method) >
<#if item_index &gt; 0 && json != “[” >
<#local json = json +’,’ >
</#if>
<#local json = json + objectToJsonFunction(item)>
<#elseif item?is_hash>
<#if item_index &gt; 0 && json != “[” >
<#local json = json +’,’ >
</#if>
<#local json = json + objectToJsonFunction(item)>
</#if>
</#list>
<#return json + ‘]’>
<#elseif object?is_hash>
<#local json = “{“>
<#assign keys = object?keys>
<#list keys as key>
<#if object[key]?? && !(object[key]?is_method) && key != “class”>
<#if object[key]?is_number>
<#if key_index &gt; 0 && json != “{” >
<#local json = json +’,’ >
</#if>
<#local json = json + ‘”${key}”: ${object[key]}’>
<#elseif object[key]?is_string>
<#if key_index &gt; 0 && json != “{” >
<#local json = json +’,’ >
</#if>
<#local json = json + ‘”${key}”: “${object[key]?html!””?js_string}”‘>
<#elseif object[key]?is_boolean >
<#if key_index &gt; 0 && json != “{” >
<#local json = json +’,’ >
</#if>
<#local json = json + ‘”${key}”: ${object[key]?string(“true”, “false”)}’>
<#elseif object[key]?is_enumerable >
<#if key_index &gt; 0 && json != “{” >
<#local json = json +’,’ >
</#if>
<#local json = json + ‘”${key}”:’+ objectToJsonFunction(object[key])>
<#elseif object[key]?is_hash>
<#if key_index &gt; 0 && json != “{” >
<#local json = json +’,’ >
</#if>
<#local json = json + ‘”${key}”:’+ objectToJsonFunction(object[key])>
</#if>
</#if>
</#list>
<#return json +”}”>
</#if>
<#else>
<#return “{}”>
</#if>
</#function>
  1. 去除 calss字段
  2. 去除多余的逗号
  3. 解决对象中的对象无法解析问题,原因是 is_string 会把对象中的对象 toString,导致走到这个逻辑

转换时间函数

附上一个转换时间的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<#– 格式化时间为 几秒前 这样,传参 long time –>
<#function showTime longTime>
<#if longTime??>
<#if (.now?long) &lt; longTime >
<#return “1秒前”>
<#elseif (.now?string.yyyy) != (longTime?number_to_datetime?string.yyyy)>
<#return longTime?number_to_datetime?string[“yyyy年MM月dd日”]>
<#elseif (.now?string.MM) != (longTime?number_to_datetime?string.MM) || (.now?string.dd) != (longTime?number_to_datetime?string.dd) >
<#return longTime?number_to_datetime?string[“MM月dd日”]>
<#elseif (.now?string.HH) != (longTime?number_to_datetime?string.HH) >
<#return longTime?number_to_datetime?string[“HH:mm”]>
<#elseif (.now?string.mm) != (longTime?number_to_datetime?string.mm) >
<#return (.now?string.mm?number – longTime?number_to_datetime?string.mm?number)+’分钟前’>
<#elseif (.now?string.ss) != (longTime?number_to_datetime?string.ss) >
<#return (.now?string.ss?number – longTime?number_to_datetime?string.ss?number)+’秒前’>
<#else>
<#return ‘1秒前’>
</#if>
<#else>
<#return “”>
</#if>
</#function>

谢谢!

转载请注明出处:http://www.haomou.net/2016/01/07/2016_web_read/
欢迎关注皓眸学问公众号(扫描左侧二维码),每天好文、新技术!任何学习疑问或者工作问题都可以给我留言、互动。T_T 皓眸大前端开发学习 T_T

未经允许不得转载:皓眸大前端 » freemarker中将object转换为json

赞 (1)
分享到:更多 ()

评论 0