如何在Jasper Reports中从JSON数据源渲染嵌套表格?
修复Jasper报表嵌套JSON数据不显示问题
问题背景
JSON数据源
{ "details": [ { "name": "Name 1", "head": [ { "isin": "ISIN 1", "coupon": "Coupon 1" } ] }, { "name": "Name 2", "head": [ { "isin": "ISIN 2", "coupon": "Coupon 2" } ] } ] }
期望渲染效果
依次展示以下独立表格:
- 仅包含
Name 1表头的表格 - 包含
ISIN 1、Coupon 1表头的表格 - 仅包含
Name 2表头的表格 - 包含
ISIN 2、Coupon 2表头的表格
现有Jasper报表代码
<?xml version="1.0" encoding="UTF-8"?> <jasperReport uuid="13bb06fa-a8ce-41f8-b3e4-a094f892f221"> <property name="com.jaspersoft.studio.data.defaultdataadapter" value="JSONAdapter"/> <subDataset name="datasetDetails" uuid="3f8c902f-fffd-48fe-b65f-46e976854490"> <property name="com.jaspersoft.studio.data.defaultdataadapter" value="JSONAdapter"/> <queryString language="json"> <![CDATA[details]]> </queryString> <field name="name" class="java.lang.String"> <property name="net.sf.jasperreports.json.field.expression" value="name"/> <fieldDescription><![CDATA[name]]></fieldDescription> </field> <field name="head" class="net.sf.jasperreports.engine.data.JsonDataSource"> <property name="net.sf.jasperreports.json.field.expression" value="head"/> <fieldDescription><![CDATA[head]]></fieldDescription> </field> </subDataset> <subDataset name="datasetDetailsHead" uuid="a91998cc-c1fa-4802-868d-90cb9a24636d"> <property name="com.jaspersoft.studio.data.defaultdataadapter" value="JSONAdapter"/> <queryString language="json"> <![CDATA[details.head]]> </queryString> <field name="isin" class="java.lang.String"> <property name="net.sf.jasperreports.json.field.expression" value="isin"/> <fieldDescription><![CDATA[isin]]></fieldDescription> </field> <field name="coupon" class="java.lang.String"> <property name="net.sf.jasperreports.json.field.expression" value="coupon"/> <fieldDescription><![CDATA[coupon]]></fieldDescription> </field> </subDataset> <queryString language="JSON"> <![CDATA[]]> </queryString> <detail> <band> <componentElement> <jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd"> <datasetRun subDataset="datasetDetails" uuid="3ca38bbd-cd5a-44c4-98bb-2e993e3a4fc4"> <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("details")]]></dataSourceExpression> </datasetRun> <jr:column> <jr:detailCell> <frame> <textField> <textFieldExpression><![CDATA[$F{name}]]></textFieldExpression> </textField> </frame> <frame> <componentElement> <jr:table> <datasetRun subDataset="datasetDetailsHeadBond" uuid="998a8505-69bb-493a-8c3a-5dc7a0e62d42"> <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("details.head")]]></dataSourceExpression> </datasetRun> <jr:column> <jr:detailCell> <textField> <textFieldExpression><![CDATA[$F{isin}]]></textFieldExpression> </textField> </jr:detailCell> </jr:column> <jr:column > <jr:detailCell > <textField> <textFieldExpression><![CDATA[$F{coupon}]]></textFieldExpression> </textField> </jr:detailCell> </jr:column> </jr:table> </componentElement> </frame> </jr:detailCell> </jr:column> </jr:table> </componentElement> </band> </detail> </jasperReport>
问题现象
渲染报表时,仅能看到外层的Name 1、Name 2数据,嵌套的head(ISIN、Coupon)数据完全无法展示。
修复步骤与修正代码
核心问题分析
- 子数据集名称不匹配:嵌套表格引用的子数据集是
datasetDetailsHeadBond,但实际定义的是datasetDetailsHead,名称错误导致无法找到对应数据集。 - 数据源上下文错误:内层表格直接使用
REPORT_DATA_SOURCE获取details.head,会遍历所有head数据,而非当前外层行对应的专属head数据。应该使用外层数据集里定义的$F{head}字段(已映射为JsonDataSource类型)作为内层表格的数据源。 - 内层数据集queryString冗余:内层数据集不需要指定
details.head作为查询路径,因为已经基于当前行的head数据源,直接留空即可。
修正后的完整代码
<?xml version="1.0" encoding="UTF-8"?> <jasperReport uuid="13bb06fa-a8ce-41f8-b3e4-a094f892f221"> <property name="com.jaspersoft.studio.data.defaultdataadapter" value="JSONAdapter"/> <subDataset name="datasetDetails" uuid="3f8c902f-fffd-48fe-b65f-46e976854490"> <property name="com.jaspersoft.studio.data.defaultdataadapter" value="JSONAdapter"/> <queryString language="json"> <![CDATA[details]]> </queryString> <field name="name" class="java.lang.String"> <property name="net.sf.jasperreports.json.field.expression" value="name"/> <fieldDescription><![CDATA[name]]></fieldDescription> </field> <field name="head" class="net.sf.jasperreports.engine.data.JsonDataSource"> <property name="net.sf.jasperreports.json.field.expression" value="head"/> <fieldDescription><![CDATA[head]]></fieldDescription> </field> </subDataset> <subDataset name="datasetDetailsHead" uuid="a91998cc-c1fa-4802-868d-90cb9a24636d"> <property name="com.jaspersoft.studio.data.defaultdataadapter" value="JSONAdapter"/> <queryString language="json"> <![CDATA[]]> </queryString> <field name="isin" class="java.lang.String"> <property name="net.sf.jasperreports.json.field.expression" value="isin"/> <fieldDescription><![CDATA[isin]]></fieldDescription> </field> <field name="coupon" class="java.lang.String"> <property name="net.sf.jasperreports.json.field.expression" value="coupon"/> <fieldDescription><![CDATA[coupon]]></fieldDescription> </field> </subDataset> <queryString language="JSON"> <![CDATA[]]> </queryString> <detail> <band> <componentElement> <jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd"> <datasetRun subDataset="datasetDetails" uuid="3ca38bbd-cd5a-44c4-98bb-2e993e3a4fc4"> <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("details")]]></dataSourceExpression> </datasetRun> <jr:column> <jr:detailCell> <!-- 显示Name的表格 --> <frame> <textField> <textFieldExpression><![CDATA[$F{name}]]></textFieldExpression> </textField> </frame> <!-- 嵌套显示head数据的表格 --> <frame> <componentElement> <jr:table> <datasetRun subDataset="datasetDetailsHead" uuid="998a8505-69bb-493a-8c3a-5dc7a0e62d42"> <!-- 使用当前行的head字段作为数据源 --> <dataSourceExpression><![CDATA[$F{head}]]></dataSourceExpression> </datasetRun> <jr:column> <jr:detailCell> <textField> <textFieldExpression><![CDATA[$F{isin}]]></textFieldExpression> </textField> </jr:detailCell> </jr:column> <jr:column> <jr:detailCell> <textField> <textFieldExpression><![CDATA[$F{coupon}]]></textFieldExpression> </textField> </jr:detailCell> </jr:column> </jr:table> </componentElement> </frame> </jr:detailCell> </jr:column> </jr:table> </componentElement> </band> </detail> </jasperReport>
内容的提问来源于stack exchange,提问作者Evgeniy
相关产品推荐
相关产品推荐

