Rafal
Rafal

Reputation: 469

How to access value of field from another data source (JSON) in JasperReports?

I'm using TIBCO Jaspersoft® Studio 6.3.1 final. I'm trying to create a report using two datasources (the format is JSON).

The structure of JSON is like:

{    
    "first":
        {"parameter1" : 123},
    "second":[
        {"key" : 1},
        {"key" : 2}
    ]
}

So I have two datasources. One for the first object (firstSource) and another (secondSource) for second object (array of objects).

The array (second) is printed in the table component. I'd like to access a field from first object (first.parameter1) and print it in the table header.

The table is using this dataset:

<datasetRun uuid="4ee63b06-f4ee-45b4-9da8-3dabc3e7a09d">
    <dataSourceExpression> <![CDATA[$P{secondSource})]]></dataSourceExpression>
</datasetRun>

Then I'm printing its fields using $F{key}.

Do you know how can I access the parameter1 of the first object from table? Maybe using some sort of $V{} variable or merging both datasources?

I tried to use subDataSource and subDataSet approach without any luck.

Here's something I'd like to achieve in the result table:

result table

Upvotes: 3

Views: 6337

Answers (1)

Petter Friberg
Petter Friberg

Reputation: 21710

Let me start with saying that json structure that you have in question is not the best structure to dynamically handle your expected output, it would have been better if parameter1 was actually inside the second node, see this How to create multiple tables in jasper report using json as a datasource? for how you could have handled and access the nodes if this was the case.

Anyway

Yes you are right in jasper reports you should think by datasource. In your expected output you basically have 2 datasources second which is your table and first which is your header. Yes first is only 1 record but to access it you can create a datasource for it and then use a component or a subreport to display it.

Considering this, one solution to your problem would be

  1. Create a dataset for the table (field is key), passing as datasource the second node

  2. Create a dataset for the header (field is parameter1), use this dataset in table to show the value.

Example

<?xml version="1.0" encoding="UTF-8"?>
<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="json_access_var" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="80e30745-0db9-476f-8bbb-cbc60d1ca90f">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="JsonTest2"/>
    <style name="Table_CH" mode="Opaque" backcolor="#BFE1FF">
        <box>
            <pen lineWidth="0.5" lineColor="#000000"/>
            <topPen lineWidth="0.5" lineColor="#000000"/>
            <leftPen lineWidth="0.5" lineColor="#000000"/>
            <bottomPen lineWidth="0.5" lineColor="#000000"/>
            <rightPen lineWidth="0.5" lineColor="#000000"/>
        </box>
    </style>
    <style name="Table_TD" mode="Opaque" backcolor="#FFFFFF">
        <box>
            <pen lineWidth="0.5" lineColor="#000000"/>
            <topPen lineWidth="0.5" lineColor="#000000"/>
            <leftPen lineWidth="0.5" lineColor="#000000"/>
            <bottomPen lineWidth="0.5" lineColor="#000000"/>
            <rightPen lineWidth="0.5" lineColor="#000000"/>
        </box>
    </style>
    <subDataset name="DatasetMain" uuid="7918eaef-d2f7-4cdd-9b84-e2660b2bfed8">
        <parameter name="mainDatasource" class="net.sf.jasperreports.engine.data.JsonDataSource"/>
        <queryString language="JSON">
            <![CDATA[]]>
        </queryString>
        <field name="key" class="java.lang.String">
            <fieldDescription><![CDATA[key]]></fieldDescription>
        </field>
    </subDataset>
    <subDataset name="DatasetTitle" uuid="7918eaef-d2f7-4cdd-9b84-e2660b2bfed8">
        <queryString language="JSON">
            <![CDATA[]]>
        </queryString>
        <field name="parameter1" class="java.lang.String">
            <fieldDescription><![CDATA[parameter1]]></fieldDescription>
        </field>
    </subDataset>
    <parameter name="JSON_INPUT_STREAM" class="java.io.InputStream" isForPrompting="false"/>
    <queryString language="JSON">
        <![CDATA[]]>
    </queryString>
    <summary>
        <band height="260" splitType="Stretch">
            <componentElement>
                <reportElement x="0" y="0" width="200" height="60" uuid="40093b50-bd8d-4d56-8d1d-9f2e9cf86106">
                    <property name="com.jaspersoft.studio.layout" value="com.jaspersoft.studio.editor.layout.VerticalRowLayout"/>
                    <property name="com.jaspersoft.studio.table.style.column_header" value="Table_CH"/>
                    <property name="com.jaspersoft.studio.table.style.detail" value="Table_TD"/>
                </reportElement>
                <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="DatasetMain" uuid="0247b2fb-527b-4dc2-af7f-9bcd75e8715a">
                        <datasetParameter name="mainDatasource">
                            <datasetParameterExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE})]]></datasetParameterExpression>
                        </datasetParameter>
                        <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("second")]]></dataSourceExpression>
                    </datasetRun>
                    <jr:column width="200" uuid="25910003-959c-4e31-a91e-555e4aaf0bec">
                        <jr:columnHeader style="Table_CH" height="30">
                            <componentElement>
                                <reportElement x="0" y="0" width="200" height="30" uuid="da5b13da-671f-4eb6-bbf1-e455b293e4ce"/>
                                <jr:list printOrder="Vertical">
                                    <datasetRun subDataset="DatasetTitle" uuid="d0a6bf94-cec6-4a75-96ec-4ae046ee90cc">
                                        <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{mainDatasource}).subDataSource("first")]]></dataSourceExpression>
                                    </datasetRun>
                                    <jr:listContents height="30" width="200">
                                        <textField>
                                            <reportElement x="0" y="0" width="200" height="30" uuid="2cd239b8-93ac-4cd2-82eb-f22db96dd010"/>
                                            <textElement textAlignment="Center" verticalAlignment="Middle"/>
                                            <textFieldExpression><![CDATA[$F{parameter1}]]></textFieldExpression>
                                        </textField>
                                    </jr:listContents>
                                </jr:list>
                            </componentElement>
                        </jr:columnHeader>
                        <jr:detailCell style="Table_TD" height="30">
                            <textField>
                                <reportElement x="0" y="0" width="200" height="30" uuid="24b2ba9b-57d0-4840-8333-70247f595e21"/>
                                <textElement textAlignment="Center" verticalAlignment="Middle"/>
                                <textFieldExpression><![CDATA[$F{key}]]></textFieldExpression>
                            </textField>
                        </jr:detailCell>
                    </jr:column>
                </jr:table>
            </componentElement>
        </band>
    </summary>
</jasperReport>

Notes:

  1. In DatasetMain I create a parameter so I can access the report main datasource (the whole json file) again this time inside the table and create the new subDataSource for first

  2. In the header I use a jr:list component to display the value of my second datasource (parameter1), you could also use a simple subreport to extract this value.

Output (using json provided in question)

Result

Upvotes: 1

Related Questions