JasperReports 4.5.1使用JSON数据源遇JRExpressionEvalException及数组访问问题
解决JasperReports 4.5.1中JSON数组访问异常问题
问题分析
你碰到的JRExpressionEvalException,核心原因是JSON数据源未正确定位到数组节点,或者字段表达式的JSON路径写法不符合JasperReports 4.5.1的解析规则。这个版本对JSON数据源的解析依赖明确的节点指向,尤其是数组类型的数据,必须单独指定路径才能正常遍历访问。
分步解决方案
1. 配置JSON数据源的查询路径
首先要给报表设置JSON_QUERY参数,明确告诉JasperReports要解析的数组节点位置:
- 在jrxml中添加参数定义:
<parameter name="JSON_QUERY" class="java.lang.String"> <defaultValueExpression><![CDATA["Person.Contacts"]]></defaultValueExpression> </parameter>
- 接着在报表的
dataSourceExpression中引用这个参数,直接定位到数组:
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JsonDataSource(new java.io.FileInputStream("contact.json"), $P{JSON_QUERY})]]></dataSourceExpression>
2. 正确编写数组元素的字段表达式
当数据源指向Contacts数组后,就可以直接用字段名访问数组内的属性:
- 先定义对应字段:
<field name="Type" class="java.lang.String"/> <field name="Number" class="java.lang.String"/>
- 在报表文本框中引用字段时,直接使用
$F{Type}和$F{Number}即可:
<textField> <reportElement x="10" y="10" width="100" height="20"/> <textFieldExpression><![CDATA[$F{Type}]]></textFieldExpression> </textField> <textField> <reportElement x="120" y="10" width="150" height="20"/> <textFieldExpression><![CDATA[$F{Number}]]></textFieldExpression> </textField>
3. 用List组件同时展示主数据和数组(主报表+子组件方式)
如果需要在主报表里同时显示Person的基本信息和Contacts数组,推荐使用List组件:
- 主报表数据源先指向
Person节点:
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JsonDataSource(new java.io.FileInputStream("contact.json"), "Person")]]></dataSourceExpression>
- 定义Person的基础字段:
<field name="FirstName" class="java.lang.String"/> <field name="LastName" class="java.lang.String"/>
- 添加List组件,将其数据源设置为
Contacts数组:
<componentElement> <reportElement x="10" y="50" width="300" height="100"/> <jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd"> <datasetRun> <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JsonDataSource(((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).getCurrentNode().get("Contacts"))]]></dataSourceExpression> </datasetRun> <jr:listContents height="20" width="300"> <textField> <reportElement x="10" y="0" width="100" height="20"/> <textFieldExpression><![CDATA[$F{Type}]]></textFieldExpression> </textField> <textField> <reportElement x="120" y="0" width="150" height="20"/> <textFieldExpression><![CDATA[$F{Number}]]></textFieldExpression> </textField> </jr:listContents> </jr:list> </componentElement>
注意事项
- JasperReports 4.5.1的JSON数据源不支持复杂JSONPath语法,尽量用简单的层级路径(如
Parent.Child.Array)。 - 确保JSON文件路径正确,避免因文件找不到引发间接异常。
- 检查字段名和JSON中的键是否完全一致(区分大小写),这是容易忽略的细节。
内容的提问来源于stack exchange,提问作者fogo




