ColdFusion 是否无法返回有效的 UTF-8 JSON 对象?
Is ColdFusion not capable of returning a valid UTF-8 JSON object?
我有一个CFC脚本,其中returns一个struct,转换成JSON格式。
这是方法声明:
<CFFUNCTION name="getJSON" returntype="Struct" returnformat="JSON" output="no" access="remote">
输出看起来很好,但不是 UTF-8。
我试过这个:
<CFCONTENT type="application/json; charset=utf-8">
<CFPROCESSINGDIRECTIVE pageEncoding="utf-8">
<CFSCRIPT>
SetEncoding("url", "utf-8");
SetEncoding("form", "utf-8");
</CFSCRIPT>
并且我将 .cfc 文件保存为带 BOM 的 UTF-8。
我想将其用作 Jasper 报告的数据源,
但我总是收到此错误消息:
Invalid UTF-8 middle byte 0x74
at [Source: java.io.ByteArrayInputStream@6c2071a7; line: 1, column: 745]
JSON 数据包含德语变音符号。
其中第一个在这个位置:"line: 1, column: 745".
创建数据源时出现错误。 InputStream 不是 UTF-8。
jsonUrl = getParam('JSON_URL', ReportParamArray);
inputStream = CreateObject("java", "java.net.URL").init(jsonUrl).openConnection().getInputStream();
jasperPrint = jasFillManager.fillReport(jasReport, parameters,
CreateObject("java", "net.sf.jasperreports.engine.data.JsonDataSource").init(inputStream));
这是完整的 Stacktrace:
Error evaluating expression :
Source text : ((net.sf.jasperreports.engine.data.JsonDataSource) $P{REPORT_DATA_SOURCE}).subDataSource("ARBEITSRAPPORT")
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1284):1284
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:588):588
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidOther(UTF8StreamJsonParser.java:2832):2832
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidOther(UTF8StreamJsonParser.java:2839):2839
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._decodeUtf8_3fast(UTF8StreamJsonParser.java:2661):2661
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishString2(UTF8StreamJsonParser.java:1962):1962
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishString(UTF8StreamJsonParser.java:1911):1911
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.getText(UTF8StreamJsonParser.java:276):276
at com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer.deserializeObject(JsonNodeDeserializer.java:203):203
at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:58):58
at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:15):15
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2580):2580
at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:1500):1500
at net.sf.jasperreports.engine.data.JsonDataSource.(JsonDataSource.java:101):101
at net.sf.jasperreports.engine.data.JsonDataSource.subDataSource(JsonDataSource.java:448):448
at rechnungen_1441802385613_104250.evaluate(rechnungen_1441802385613_104250:415):415
at net.sf.jasperreports.engine.fill.JREvaluator.evaluate(JREvaluator.java:231):231
at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:591):591
at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:559):559
at net.sf.jasperreports.engine.fill.JRFillElement.evaluateExpression(JRFillElement.java:1001):1001
at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluateSubreport(JRFillSubreport.java:392):392
at net.sf.jasperreports.components.table.fill.FillTableSubreport.evaluateSubreport(FillTableSubreport.java:101):101
at net.sf.jasperreports.components.table.fill.FillTable.evaluate(FillTable.java:117):117
at net.sf.jasperreports.engine.fill.JRFillComponentElement.evaluate(JRFillComponentElement.java:108):108
at net.sf.jasperreports.engine.fill.JRFillElementContainer.evaluate(JRFillElementContainer.java:259):259
at net.sf.jasperreports.engine.fill.JRFillBand.evaluate(JRFillBand.java:456):456
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillColumnBand(JRVerticalFiller.java:2044):2044
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillDetail(JRVerticalFiller.java:778):778
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReportStart(JRVerticalFiller.java:288):288
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:151):151
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:932):932
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:864):864
at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:88):88
at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.java:653):653
at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:969):969
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method):-2
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source):-1
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source):-1
at java.lang.reflect.Method.invoke(Unknown Source):-1
at lucee.runtime.reflection.pairs.MethodInstance.invoke(MethodInstance.java:55):55
at lucee.runtime.java.JavaObject.call(JavaObject.java:234):234
at lucee.runtime.java.JavaObject.call(JavaObject.java:256):256
at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:742):742
at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1589):1589
at cfdocs.gebman.reports.reportsystemjasper_cfm$cf.call(D:\ICS\Internet\CFDOCS\gebman\reports\reportSystemJasper.cfm:158):158
at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:950):950
at lucee.runtime.tag.CFTag.doInclude(CFTag.java:323):323
at lucee.runtime.tag.CFTag.cfmlStartTag(CFTag.java:245):245
at lucee.runtime.tag.CFTag.doStartTag(CFTag.java:177):177
at cfdocs.gebman.reports.rechnungindex_cfm$cf.call(D:\ICS\Internet\CFDOCS\gebman\reports\rechnungIndex.cfm:151):151
at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:950):950
at lucee.runtime.listener.ClassicAppListener._onRequest(ClassicAppListener.java:56):56
at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:36):36
at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2257):2257
at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2224):2224
at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:456):456
at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:47):47
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728):728
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305):305
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210):210
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222):222
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123):123
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472):472
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171):171
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99):99
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118):118
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407):407
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004):1004
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589):589
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310):310
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source):-1
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source):-1
at java.lang.Thread.run(Unknown Source):-1
如何确保 CFC returns 有效的 UTF-8 内容?
在 Leigh 的帮助下,我已经解决了这个问题。
getInputStream()
函数没有使用 UTF-8。即使我将默认文件编码设置为 UTF-8,它也不起作用。
为确保报告生成器使用 UTF-8,我重新创建了输入流并在此过程中应用了编码。
jsonUrl = getParam('JSON_URL', ReportParamArray);
// Get the Input Stream
inputStream = CreateObject("java", "java.net.URL").init(jsonUrl).openConnection().getInputStream();
// Convert the stream to a byte array
bytes = CreateObject("java", "org.apache.commons.io.IOUtils").toByteArray(inputStream);
// Convert bytes to string
str = CreateObject("java", "java.lang.String").init(bytes);
// Create a new UTF-8 input stream
inputStreamUTF8 = CreateObject("java", "java.io.ByteArrayInputStream").init(str.getBytes("UTF-8"));
// Fill the report with our new input stream
jasperPrint = jasFillManager.fillReport(jasReport, parameters,
CreateObject("java", "net.sf.jasperreports.engine.data.JsonDataSource").init(inputStreamUTF8));
就性能而言,这可能不是完美的解决方案,但它确实有效,我摆脱了编码地狱。
我有一个CFC脚本,其中returns一个struct,转换成JSON格式。 这是方法声明:
<CFFUNCTION name="getJSON" returntype="Struct" returnformat="JSON" output="no" access="remote">
输出看起来很好,但不是 UTF-8。
我试过这个:
<CFCONTENT type="application/json; charset=utf-8">
<CFPROCESSINGDIRECTIVE pageEncoding="utf-8">
<CFSCRIPT>
SetEncoding("url", "utf-8");
SetEncoding("form", "utf-8");
</CFSCRIPT>
并且我将 .cfc 文件保存为带 BOM 的 UTF-8。
我想将其用作 Jasper 报告的数据源, 但我总是收到此错误消息:
Invalid UTF-8 middle byte 0x74
at [Source: java.io.ByteArrayInputStream@6c2071a7; line: 1, column: 745]
JSON 数据包含德语变音符号。 其中第一个在这个位置:"line: 1, column: 745".
创建数据源时出现错误。 InputStream 不是 UTF-8。
jsonUrl = getParam('JSON_URL', ReportParamArray);
inputStream = CreateObject("java", "java.net.URL").init(jsonUrl).openConnection().getInputStream();
jasperPrint = jasFillManager.fillReport(jasReport, parameters,
CreateObject("java", "net.sf.jasperreports.engine.data.JsonDataSource").init(inputStream));
这是完整的 Stacktrace:
Error evaluating expression :
Source text : ((net.sf.jasperreports.engine.data.JsonDataSource) $P{REPORT_DATA_SOURCE}).subDataSource("ARBEITSRAPPORT")
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1284):1284
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:588):588
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidOther(UTF8StreamJsonParser.java:2832):2832
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidOther(UTF8StreamJsonParser.java:2839):2839
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._decodeUtf8_3fast(UTF8StreamJsonParser.java:2661):2661
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishString2(UTF8StreamJsonParser.java:1962):1962
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishString(UTF8StreamJsonParser.java:1911):1911
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.getText(UTF8StreamJsonParser.java:276):276
at com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer.deserializeObject(JsonNodeDeserializer.java:203):203
at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:58):58
at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:15):15
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2580):2580
at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:1500):1500
at net.sf.jasperreports.engine.data.JsonDataSource.(JsonDataSource.java:101):101
at net.sf.jasperreports.engine.data.JsonDataSource.subDataSource(JsonDataSource.java:448):448
at rechnungen_1441802385613_104250.evaluate(rechnungen_1441802385613_104250:415):415
at net.sf.jasperreports.engine.fill.JREvaluator.evaluate(JREvaluator.java:231):231
at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:591):591
at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:559):559
at net.sf.jasperreports.engine.fill.JRFillElement.evaluateExpression(JRFillElement.java:1001):1001
at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluateSubreport(JRFillSubreport.java:392):392
at net.sf.jasperreports.components.table.fill.FillTableSubreport.evaluateSubreport(FillTableSubreport.java:101):101
at net.sf.jasperreports.components.table.fill.FillTable.evaluate(FillTable.java:117):117
at net.sf.jasperreports.engine.fill.JRFillComponentElement.evaluate(JRFillComponentElement.java:108):108
at net.sf.jasperreports.engine.fill.JRFillElementContainer.evaluate(JRFillElementContainer.java:259):259
at net.sf.jasperreports.engine.fill.JRFillBand.evaluate(JRFillBand.java:456):456
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillColumnBand(JRVerticalFiller.java:2044):2044
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillDetail(JRVerticalFiller.java:778):778
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReportStart(JRVerticalFiller.java:288):288
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:151):151
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:932):932
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:864):864
at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:88):88
at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.java:653):653
at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:969):969
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method):-2
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source):-1
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source):-1
at java.lang.reflect.Method.invoke(Unknown Source):-1
at lucee.runtime.reflection.pairs.MethodInstance.invoke(MethodInstance.java:55):55
at lucee.runtime.java.JavaObject.call(JavaObject.java:234):234
at lucee.runtime.java.JavaObject.call(JavaObject.java:256):256
at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:742):742
at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1589):1589
at cfdocs.gebman.reports.reportsystemjasper_cfm$cf.call(D:\ICS\Internet\CFDOCS\gebman\reports\reportSystemJasper.cfm:158):158
at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:950):950
at lucee.runtime.tag.CFTag.doInclude(CFTag.java:323):323
at lucee.runtime.tag.CFTag.cfmlStartTag(CFTag.java:245):245
at lucee.runtime.tag.CFTag.doStartTag(CFTag.java:177):177
at cfdocs.gebman.reports.rechnungindex_cfm$cf.call(D:\ICS\Internet\CFDOCS\gebman\reports\rechnungIndex.cfm:151):151
at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:950):950
at lucee.runtime.listener.ClassicAppListener._onRequest(ClassicAppListener.java:56):56
at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:36):36
at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2257):2257
at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2224):2224
at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:456):456
at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:47):47
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728):728
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305):305
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210):210
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222):222
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123):123
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472):472
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171):171
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99):99
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118):118
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407):407
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004):1004
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589):589
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310):310
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source):-1
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source):-1
at java.lang.Thread.run(Unknown Source):-1
如何确保 CFC returns 有效的 UTF-8 内容?
在 Leigh 的帮助下,我已经解决了这个问题。
getInputStream()
函数没有使用 UTF-8。即使我将默认文件编码设置为 UTF-8,它也不起作用。
为确保报告生成器使用 UTF-8,我重新创建了输入流并在此过程中应用了编码。
jsonUrl = getParam('JSON_URL', ReportParamArray);
// Get the Input Stream
inputStream = CreateObject("java", "java.net.URL").init(jsonUrl).openConnection().getInputStream();
// Convert the stream to a byte array
bytes = CreateObject("java", "org.apache.commons.io.IOUtils").toByteArray(inputStream);
// Convert bytes to string
str = CreateObject("java", "java.lang.String").init(bytes);
// Create a new UTF-8 input stream
inputStreamUTF8 = CreateObject("java", "java.io.ByteArrayInputStream").init(str.getBytes("UTF-8"));
// Fill the report with our new input stream
jasperPrint = jasFillManager.fillReport(jasReport, parameters,
CreateObject("java", "net.sf.jasperreports.engine.data.JsonDataSource").init(inputStreamUTF8));
就性能而言,这可能不是完美的解决方案,但它确实有效,我摆脱了编码地狱。