如何在FreeMarker模板处理中转义Unicode符号?
解决FreeMarker 2.3.28中?eval解析含en-dash/em-dash的JSON报错问题
这个问题我之前也碰到过,本质是**?eval的设计初衷不是用来解析JSON**,而是解析FreeMarker表达式——这就是为什么特殊破折号会触发词法错误的核心原因。
错误原因拆解
当你用?eval处理JSON字符串时,FreeMarker会把整个字符串当作FTL语法来解析。en-dash(–)和em-dash(—)这类符号不在FTL的合法语法规则里,词法分析器会把它们当成未知的语法标记,直接抛出lexical error: encountered "u" (117)这类错误。而版权(©)、商标(®)符号只是普通Unicode字符,FTL会把它们当作字符串内容处理,所以不会出问题。
解决方案(按推荐程度排序)
1. 在Java层提前解析JSON(最稳妥)
既然你的需求是JSON转XML,完全可以先在Java代码里把JSON解析成Java对象(比如Map<String, Object>或自定义POJO),再把这个对象传入FreeMarker模板。模板直接访问对象属性,根本不需要用?eval。
举个Jackson解析的示例:
// 假设你的JSON字符串是jsonStr ObjectMapper objectMapper = new ObjectMapper(); Map<String, Object> data = objectMapper.readValue( jsonStr, new TypeReference<Map<String, Object>>() {} ); // 把解析后的对象传入模板 Template template = configuration.getTemplate("your-template.ftl"); template.process( data, new OutputStreamWriter(outputStream, StandardCharsets.UTF_8) );
之后模板里直接用${text}就能访问{"text": "Hello – World"}里的内容,所有Unicode符号都能正常输出,完全避开?eval的坑。
2. 给模板注册自定义JSON解析方法(适配2.3.28)
因为FreeMarker 2.3.28还没内置?eval_json(这个特性在2.3.29才加入),如果必须在模板里处理JSON字符串,可以自己在Java层注册一个用专业JSON库(Jackson/Gson)解析的方法。
步骤1:注册自定义方法到FreeMarker配置
Configuration cfg = new Configuration(Configuration.VERSION_2_3_28); cfg.setDefaultEncoding("UTF-8"); // 注册parseJson方法,用于模板内解析JSON cfg.setSharedVariable("parseJson", new TemplateMethodModelEx() { @Override public Object exec(List arguments) throws TemplateModelException { if (arguments.size() != 1) { throw new TemplateModelException("parseJson需要1个参数:JSON字符串"); } String jsonStr = ((SimpleScalar) arguments.get(0)).getAsString(); try { ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(jsonStr, Object.class); } catch (IOException e) { throw new TemplateModelException("JSON解析失败:" + e.getMessage(), e); } } });
步骤2:在模板中调用自定义方法
<#assign jsonData = parseJson(jsonString)> <!-- 正常访问解析后的属性 --> <text>${jsonData.text}</text>
内容的提问来源于stack exchange,提问作者boredDev
相关产品推荐
相关产品推荐

