Search code examples
jsonjasper-reportssubreport

How to pass a JSON array value into a Jasper Reports subreport?


Having a problem with Jasper Reports and Subtables.

I'm working with the following JSON format:

[
  {
    "dataObjects": [
      {
        "objectId": "025b3873ebe640aa9d6a34f9306548ae",
        "employeeFullName": "John Smith",
        "employeeGrade": "GS12"
      },
      {
        "objectId": "08b9300f62dc498f86c675ac5897b4c9",
        "employeeFullName": "Bill Johnson",
        "employeeGrade": "GS14"
      }
    ]
  },
  {
    "dataObjects": [
      ...
    ]
  },
  {
    "dataObjects": [
      ...
    ]
  },
  {
    "dataObjects": [
      ...
    ]
  }
]

The data returns as an array of four JSON objects. Each object contains the result of a query under .dataObjects

I need to be able to display this data as four separate subreports, charts, in this case.

I'm not seeing a way to pass the data from the parent to the subreport in the case of an array.

Playing with reformatting the data gives me:

{
  "report0": {
    "dataObjects": [
      {
        "objectId": "025b3873ebe640aa9d6a34f9306548ae",
        "employeeFullName": "John Smith",
        "employeeGrade": "GS12"
      },
      {
        "objectId": "08b9300f62dc498f86c675ac5897b4c9",
        "employeeFullName": "Bill Johnson",
        "employeeGrade": "GS14"
      }
    ],
  },
  "report1": {
    "dataObjects": [
      ...
    ]
  },
  "report2": {
    "dataObjects": [
      ...
    ]
  },
  "report3": {
    "dataObjects": [
      ...
    ]
  }  
}

and this works fine using this:

<subreport>
  <reportElement x="20" y="10" width="260" height="260" uuid="6a319da0-bd78-4f44-8445-e03b9a62cc0f"/>
  <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("report0.dataObjects")]]></dataSourceExpression>
  <subreportExpression><![CDATA["quad_1.jrxml"]]></subreportExpression>
</subreport>

But I need to be able to do it without reworking the data, I need something like this, which does not work:

<subreport>
  <reportElement x="20" y="10" width="260" height="260" uuid="6a319da0-bd78-4f44-8445-e03b9a62cc0f"/>
  <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("[0].dataObjects")]]></dataSourceExpression>
  <subreportExpression><![CDATA["quad_1.jrxml"]]></subreportExpression>
</subreport>            

Extensive Googling has not found anything about working with a json-list. Thoughts?

This was marked as a duplicate, but the duplicate does not address the issue I'm having.

I need to pass the data to subreports, each entry in the array goes to a separate subreport. I could work around the problem, possibly, as described, but the requirement is for subreports.


Solution

  • This could be achieved with JSONQL, a more capable replacement of the initial JSON language.

    Your main report could look like this(I'm reusing the same subreport just for brevity):

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Created with Jaspersoft Studio version 6.9.0.final using JasperReports Library version 6.9.0-cb8f9004be492ccc537180b49c026951f4220bf3  -->
    <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Report" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="749076bd-1ea5-4847-85e1-cf88b11c9ef6">
        <property name="com.jaspersoft.studio.data.defaultdataadapter" value="DataAdapter.xml"/>
        <queryString language="jsonql">
            <![CDATA[[0]]]>
        </queryString>
        <background>
            <band splitType="Stretch"/>
        </background>
        <summary>
            <band height="160" splitType="Stretch">
                <subreport>
                    <reportElement x="0" y="0" width="550" height="40" uuid="33bba077-fd38-4db3-b2ad-56c21a18105f"/>
                    <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonQLDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("dataObjects")]]></dataSourceExpression>
                    <subreportExpression><![CDATA["SubReport.jasper"]]></subreportExpression>
                </subreport>
                <subreport>
                    <reportElement positionType="Float" x="0" y="40" width="550" height="40" uuid="bb8ab5c7-0fe8-4398-8efc-6d648e6a3a2c"/>
                    <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonQLDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("^[1].dataObjects")]]></dataSourceExpression>
                    <subreportExpression><![CDATA["SubReport.jasper"]]></subreportExpression>
                </subreport>
                <subreport>
                    <reportElement positionType="Float" x="0" y="80" width="550" height="40" uuid="001d79d0-e850-41a9-8995-f55d6e96bc45"/>
                    <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonQLDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("^[2].dataObjects")]]></dataSourceExpression>
                    <subreportExpression><![CDATA["SubReport.jasper"]]></subreportExpression>
                </subreport>
                <subreport>
                    <reportElement positionType="Float" x="0" y="120" width="550" height="40" uuid="4d7d085b-1694-40b2-9e10-81428b1a9165"/>
                    <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonQLDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("^[3].dataObjects")]]></dataSourceExpression>
                    <subreportExpression><![CDATA["SubReport.jasper"]]></subreportExpression>
                </subreport>
            </band>
        </summary>
    </jasperReport>
    

    The important parts here are the queries:

    • the main query, [0], is pretty obvious, it just selects the first item in the array so that for the first subreport you only need to apply subDatasource() with the dataObjects key
    • the subsequent queries only travel up the JSON tree(^) to select the appropriate source object to be passed to its respective subreport