Hot questions for Using JasperReports in json

Question:

I have json object like this

{
  "data":[
    {
       "no":1,
       "name" : "yuda",
       "address" : "surabaya"
    },
    {
        "no":2,
        "name":"adi",
        "address":"jakarta"
    }
  ],
  "comp_name":"TEST CORP",
  "title":"Company employee",
  "status":"success"
}

I serve that json with http rest API and I want to create report with jasper report and I have success if I pass it as an url JsonQueryExecuterFactory.JSON_SOURCE.

My problem is that I can't include session cookie in JSON_SOURCE, the solution I'm trying is to create a http request in java code and then include it with JsonQueryExecuterFactory.JSON_INPUT_STREAM, but it's not working, it just shows blank page. Even though I update parameter from $P{net.sf.jasperreports.json.source} to $P{JSON_INPUT_STREAM} it doesn't work.


Answer:

This is a full example of loading your json from a http request via java (you can add headers as you like), using a subreport to pass the data node as a subDataSource

Example URL: http://www.jdd.it/so/jsonTest.json *Your json is available on this url

Main report (jsonMain.jrxml)
<?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="JsonMain" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="15289120-bdf0-4edd-905c-647999c3c0cc">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="json"/>
    <parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
        <defaultValueExpression><![CDATA["C:\\jdd\\..path..to..subreport\\"]]></defaultValueExpression>
    </parameter>
    <queryString language="JSON">
        <![CDATA[]]>
    </queryString>
    <field name="comp_name" class="java.lang.String">
        <fieldDescription><![CDATA[comp_name]]></fieldDescription>
    </field>
    <field name="title" class="java.lang.String">
        <fieldDescription><![CDATA[title]]></fieldDescription>
    </field>
    <field name="status" class="java.lang.String">
        <fieldDescription><![CDATA[status]]></fieldDescription>
    </field>
    <detail>
        <band height="40">
            <staticText>
                <reportElement x="0" y="0" width="115" height="20" uuid="023be3f7-66fc-4718-9ca3-220c16ddc97a"/>
                <textElement verticalAlignment="Middle">
                    <font size="14" isBold="true"/>
                </textElement>
                <text><![CDATA[Company name:]]></text>
            </staticText>
            <textField>
                <reportElement x="115" y="0" width="103" height="20" uuid="15aadf03-03a1-4c05-8bf9-cdf7db09153c"/>
                <textElement verticalAlignment="Middle">
                    <font size="14" isBold="true"/>
                </textElement>
                <textFieldExpression><![CDATA[$F{comp_name}]]></textFieldExpression>
            </textField>
            <subreport>
                <reportElement x="0" y="20" width="555" height="20" uuid="c8251ce1-5de4-476f-a4cc-89717d422cc7"/>
                <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("data")]]></dataSourceExpression>
                <subreportExpression><![CDATA[$P{SUBREPORT_DIR} + "jsonMain_subreport.jasper"]]></subreportExpression>
            </subreport>
            <staticText>
                <reportElement x="218" y="0" width="39" height="20" uuid="4c8d8333-117a-4447-98ac-bfebbd28776a"/>
                <textElement verticalAlignment="Middle">
                    <font size="14" isBold="true"/>
                </textElement>
                <text><![CDATA[Title:]]></text>
            </staticText>
            <textField>
                <reportElement x="257" y="0" width="154" height="20" uuid="0f266993-1bf3-41cf-8db6-c8b5aaccef74"/>
                <textElement verticalAlignment="Middle">
                    <font size="14" isBold="true"/>
                </textElement>
                <textFieldExpression><![CDATA[$F{title}]]></textFieldExpression>
            </textField>
            <staticText>
                <reportElement x="411" y="0" width="51" height="20" uuid="9afd4de9-5155-43a6-ae63-337bb77deac8"/>
                <textElement verticalAlignment="Middle">
                    <font size="14" isBold="true"/>
                </textElement>
                <text><![CDATA[Status:]]></text>
            </staticText>
            <textField>
                <reportElement x="462" y="0" width="93" height="20" uuid="6e8ab3b0-c8eb-40f4-ade8-9dd60e34a721"/>
                <textElement verticalAlignment="Middle">
                    <font size="14" isBold="true"/>
                </textElement>
                <textFieldExpression><![CDATA[$F{status}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

The key is to subDataSource the data node ((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("data") and pass this to subreport

Subreport (jsonMain_subreport.jrxml)
<?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="jsonMain_subreport" language="java" pageWidth="555" pageHeight="802" columnWidth="555" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0" uuid="9c681432-4547-4fd8-91c1-5634ca368da6">
    <field name="no" class="java.lang.String"/>
    <field name="name" class="java.lang.String"/>
    <field name="address" class="java.lang.String"/>
    <columnHeader>
        <band height="20" splitType="Stretch">
            <staticText>
                <reportElement mode="Opaque" x="0" y="0" width="100" height="20" backcolor="#CCCCCC" uuid="3dbc394e-6a5a-45d2-8d53-c9880f3974e7"/>
                <box leftPadding="2" rightPadding="2">
                    <pen lineWidth="0.25"/>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement verticalAlignment="Middle"/>
                <text><![CDATA[No]]></text>
            </staticText>
            <staticText>
                <reportElement mode="Opaque" x="100" y="0" width="167" height="20" backcolor="#CCCCCC" uuid="2c40967a-42d5-439e-a1c3-5d41fd50f906"/>
                <box leftPadding="2" rightPadding="2">
                    <pen lineWidth="0.25"/>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement verticalAlignment="Middle"/>
                <text><![CDATA[Name]]></text>
            </staticText>
            <staticText>
                <reportElement mode="Opaque" x="267" y="0" width="288" height="20" backcolor="#CCCCCC" uuid="0d72063d-6354-4e8d-9f89-52d00d100d3e"/>
                <box leftPadding="2" rightPadding="2">
                    <pen lineWidth="0.25"/>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement verticalAlignment="Middle"/>
                <text><![CDATA[Address]]></text>
            </staticText>
        </band>
    </columnHeader>
    <detail>
        <band height="20" splitType="Stretch">
            <textField>
                <reportElement x="0" y="0" width="100" height="20" uuid="e9cc4829-5e9a-4747-a594-489b6230713c"/>
                <box leftPadding="2" rightPadding="2">
                    <pen lineWidth="0.25"/>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement verticalAlignment="Middle"/>
                <textFieldExpression><![CDATA[$F{no}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="100" y="0" width="167" height="20" uuid="1c02f144-1c6c-4704-9bfb-13ac39007841"/>
                <box leftPadding="2" rightPadding="2">
                    <pen lineWidth="0.25"/>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement verticalAlignment="Middle"/>
                <textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="267" y="0" width="288" height="20" uuid="e0b9aff3-c8e3-4895-90a2-339ffb7c856f"/>
                <box leftPadding="2" rightPadding="2">
                    <pen lineWidth="0.25"/>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement verticalAlignment="Middle"/>
                <textFieldExpression><![CDATA[$F{address}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

Nothing special in this report, the fields corresponds to the fields in your data node, remember to compile subreport to .jasper before running java code, since .jasper is indicated in main report.

Java code
//Get our main report
JasperReport report = JasperCompileManager.compileReport("jsonMain.jrxml");

//Open url connection
URLConnection urlConn = new URL("http://www.jdd.it/so/jsonTest.json").openConnection();
//set some cookies
urlConn.setRequestProperty("Cookie", "cookie1=hello; cookie2=world");

//Get the stream
try (InputStream is =urlConn.getInputStream()) {
    Map<String, Object> parametersMap = new HashMap<>();
    //Pass to parameter map
    parametersMap.put(JsonQueryExecuterFactory.JSON_INPUT_STREAM, is);
    //Fill report
    JasperPrint jasperPrint = JasperFillManager.fillReport(report, parametersMap);
    //Export to pdf
    JRPdfExporter exporter = new JRPdfExporter();
    exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
    exporter.setExporterOutput(new SimpleOutputStreamExporterOutput("json.pdf"));
    SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
    configuration.setMetadataAuthor("Me");
    exporter.setConfiguration(configuration);
    exporter.exportReport();
}
Result

Question:

I am trying to create a JasperReport using JSONDatasource that is passed by a JAVA function.

Here is my JSON that I am sending to jasper

{
  "Person": {
    "FirstName": "John",
    "LastName": "Smith",
    "Contacts": [
        {
            "Type": "Cell",
            "Number": "555-555-5555"
        },
        {
            "Type": "Home",
            "Number": "666-666-6666"
        }
    ]
  }
}

I am trying to display the phone numbers in a table. I can display the the other fields fine. But not sure how to display the table.

Here is how I am defining my Jasper fields

<field name="FirstName" class="java.lang.String">
        <property name="net.sf.jasperreports.json.field.expression" value="Person.FirstName"/>
    </field>
    <field name="LastName" class="java.lang.String">
        <<property name="net.sf.jasperreports.json.field.expression" value="Person.LastName"/>
    </field>
    <field name="Contacts" class="java.lang.String">
        <property name="net.sf.jasperreports.json.field.expression" value="Person.Contacts"/>
</field>

Answer:

With the JSON language you can access the Contacts nested array only through the means of a subDataset, with which you can populate a Table component. Here is a complete sample(I have remove the generated styles to keep the sample compact):

<?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="Report" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="81afe112-ee1b-4443-8d1c-cb6d9ab95dd8">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="stackoverflow/JSON_array_table/DataAdapter.xml"/>
    <subDataset name="ContactsSubdataset" uuid="4563e834-a9e5-43b5-9f0a-824948c73c73">
        <field name="Type" class="java.lang.String">
            <property name="net.sf.jasperreports.json.field.expression" value="Type"/>
        </field>
        <field name="Number" class="java.lang.String">
            <property name="net.sf.jasperreports.json.field.expression" value="Number"/>
        </field>
    </subDataset>
    <queryString language="json">
        <![CDATA[]]>
    </queryString>
    <field name="FirstName" class="java.lang.String">
        <property name="net.sf.jasperreports.json.field.expression" value="Person.FirstName"/>
    </field>
    <field name="LastName" class="java.lang.String">
        <property name="net.sf.jasperreports.json.field.expression" value="Person.LastName"/>
    </field>
    <detail>
        <band height="300" splitType="Stretch">
            <staticText>
                <reportElement x="0" y="0" width="80" height="30" uuid="d59811d6-a4e9-4871-a64b-f332d049e551"/>
                <text><![CDATA[First Name:]]></text>
            </staticText>
            <staticText>
                <reportElement x="0" y="30" width="80" height="30" uuid="ef25edff-1c33-4ec4-8dd1-21766039e6e3"/>
                <text><![CDATA[Last Name:]]></text>
            </staticText>
            <staticText>
                <reportElement x="0" y="60" width="80" height="30" uuid="e74bfa48-5040-4655-b419-f4f8e9f7e871"/>
                <text><![CDATA[Contacts:]]></text>
            </staticText>
            <textField>
                <reportElement x="80" y="0" width="200" height="30" uuid="49d1558c-396f-4864-b71f-41b6c7d677c2"/>
                <textFieldExpression><![CDATA[$F{FirstName}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="80" y="30" width="200" height="30" uuid="8ddaca45-a124-4c67-b2a8-50f7188097f9"/>
                <textFieldExpression><![CDATA[$F{LastName}]]></textFieldExpression>
            </textField>
            <componentElement>
                <reportElement x="80" y="60" width="200" height="60" uuid="105c3994-b8a8-4085-81ef-4a0e55efc7c6"/>
                <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="ContactsSubdataset" uuid="5459bdfb-6835-4007-8e56-566716c8c29c">
                        <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("Person.Contacts")]]></dataSourceExpression>
                    </datasetRun>
                    <jr:column width="100" uuid="b3d4c078-f65a-4213-9644-83b85b425703">
                        <jr:columnHeader height="30">
                            <staticText>
                                <reportElement x="0" y="0" width="100" height="30" uuid="4b972b67-2f1a-4843-857e-c735dfc59c82"/>
                                <text><![CDATA[Type]]></text>
                            </staticText>
                        </jr:columnHeader>
                        <jr:detailCell height="30">
                            <textField>
                                <reportElement x="0" y="0" width="100" height="30" uuid="e618a748-3273-476d-95c5-4d232260bf0a"/>
                                <textFieldExpression><![CDATA[$F{Type}]]></textFieldExpression>
                            </textField>
                        </jr:detailCell>
                    </jr:column>
                    <jr:column width="100" uuid="5b01cf7c-71bc-474a-9858-ef58479efcdc">
                        <jr:columnHeader height="30">
                            <staticText>
                                <reportElement x="0" y="0" width="100" height="30" uuid="394f2626-8c49-491d-a09c-ef7f90132741"/>
                                <text><![CDATA[Number]]></text>
                            </staticText>
                        </jr:columnHeader>
                        <jr:detailCell height="30">
                            <textField>
                                <reportElement x="0" y="0" width="100" height="30" uuid="40ddb342-5be4-43bf-9fb2-a1fda76f53af"/>
                                <textFieldExpression><![CDATA[$F{Number}]]></textFieldExpression>
                            </textField>
                        </jr:detailCell>
                    </jr:column>
                </jr:table>
            </componentElement>
        </band>
    </detail>
</jasperReport>

Question:

I am trying to get JSON data from a rest service. I know this is pretty simple for a GET service where you only have to provide the URI and Jasper studio can pull the data but I want to do this for a post rest service that also consumes some JSON input.

Workflow will be something like:

  1. Send userID in request header and some JSON parameters in request body.
  2. Get JSON data as output.
  3. Use JSON data to build report.

I am new to Jasper and am using Jasper server 6 with Japser Studio 6 but I can't find any documentation to do something like this.

I would appreciate if anyone can point me in the right direction regarding this.

The closes thing I can find is this link. From there I get that I can create a constructor which will get the data from rest service but how do I serve it to the report? Also please note that the JSON object being retrieved here is a bit complex and will have at least 2 lists with any number of items.

EDIT:

Alright so my custom adapter is like this:

package CustomDataAdapter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.json.JSONObject;

public class SearchAdapter implements JRDataSource {
/**
 * This will hold the JSON returned by generic search service
 */
private JSONObject json = null;

/**
 * Will create the object with data retrieved from service.
 */
public SearchAdapter() {
    String url = "[URL is here]";
    String request = "{searchType: \"TEST\", searchTxt: \"TEST\"}";

    // Setting up post client and request.
    HttpClient client = HttpClientBuilder.create().build();
    HttpPost post = new HttpPost(url);
    HttpResponse response = null;

    post.setHeader("userId", "1000");
    post.setHeader("Content-Type", "application/json");

    // Setting up Request payload
    HttpEntity entity = null;
    try {
        entity = new StringEntity(request);
        post.setEntity(entity);

        // do post
        response = client.execute(post);
    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    // Reading Server Response
    try {
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            throw new Exception("Search Failed");
        }

        BufferedReader in = new BufferedReader(new InputStreamReader(
                response.getEntity().getContent()));
        String inputLine;
        StringBuffer resp = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            resp.append(inputLine);
        }

        in.close();

        this.json = new JSONObject(resp.toString());
    } catch (NullPointerException e) {
        e.printStackTrace();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

/*
 * (non-Javadoc)
 * 
 * @see
 * net.sf.jasperreports.engine.JRDataSource#getFieldValue(net.sf.jasperreports
 * .engine.JRField)
 */
public Object getFieldValue(JRField field) throws JRException {
    // TODO Auto-generated method
    // stubhttp://community-static.jaspersoft.com/sites/default/files/images/0.png
    return this.json;
}

/*
 * (non-Javadoc)
 * 
 * @see net.sf.jasperreports.engine.JRDataSource#next()
 */
public boolean next() throws JRException {
    return (this.json != null);
}

/**
 * Return an instance of the class that implements the custom data adapter.
 */
public static JRDataSource getDataSource() {
    return new SearchAdapter();
}

}

I am able to create an adapter and the Test Connection feature in Jasper Studio also returns true but I cant get it to read any of the fields in the JSON and auto-generate the report. I only get a blank document. FYI the JSON is something like:

{
"key": "value",
"key": "value",
"key": [list],
"key": [list]
}

Answer:

Well, I feel stupid now but the solution was pretty easy. Turns out you cant just return a JSON object. You need to return the fields and manually add the fields in the report.

For record purposes my final code look like this:

package CustomDataAdapter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.json.JSONException;
import org.json.JSONObject;

public class SearchAdapter implements JRDataSource {

    /**
     * This will hold the JSON returned by generic search service
     */
    private JSONObject json = null;

    /**
     * Ensures that we infinitely calling the service.
     */
    private boolean flag = false;
    /**
     * Will create the object with data retrieved from service.
     */
    private void setJson() {
        String url = "[URL is here]";
        String request = "{\"searchType\": \"Test\", \"searchTxt\": \"Test\"}";

        // Setting up post client and request.
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        HttpResponse response = null;

        post.setHeader("userId", "1000");
        post.setHeader("Content-Type", "application/json");

        // Setting up Request payload
        StringEntity entity = null;
        try {
            entity = new StringEntity(request);
            post.setEntity(entity);

            // do post
            response = client.execute(post);
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // Reading Server Response
        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                // Thrown Exception in case things go wrong
                BufferedReader in = new BufferedReader(new InputStreamReader(
                        response.getEntity().getContent()));
                String inputLine;
                StringBuffer resp = new StringBuffer();
                while ((inputLine = in.readLine()) != null) {
                    resp.append(inputLine);
                }

                in.close();

                String ex = "Search Failed. Status Code: " + statusCode;
                ex += "\n Error: " + resp.toString();
                throw new Exception(ex);
            }

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    response.getEntity().getContent()));
            String inputLine;
            StringBuffer resp = new StringBuffer();
            while ((inputLine = in.readLine()) != null) {
                resp.append(inputLine);
            }

            in.close();

            this.json = new JSONObject(resp.toString());
        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * net.sf.jasperreports.engine.JRDataSource#getFieldValue(net.sf.jasperreports
     * .engine.JRField)
     */
    @Override
    public Object getFieldValue(JRField field) throws JRException {
        // TODO Auto-generated method
        // stubhttp://community-static.jaspersoft.com/sites/default/files/images/0.png
        try {
            return this.json.get(field.getName());
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see net.sf.jasperreports.engine.JRDataSource#next()
     */
    @Override
    public boolean next() throws JRException {
        if (this.json != null && !flag) {
            flag = true;
            return true;
        } else {
            return false;
        }
    }

    /**
     * Return an instance of the class that implements the custom data adapter.
     */
    public static JRDataSource getDataSource() {
        SearchAdapter adapter = new SearchAdapter();
        adapter.setJson();
        return adapter;
    }

}

Question:

I am having issues with populating data in subreport in the title band of the main report. The data is populated correctly in subreport in the detail band of the main report. I am trying to find what could be wrong in the JSON query. Any help is appreciated.

JSON Sample Data Source (expenses.json)

{
  "expenses": {
    "date": "8 Sep 2016",
    "accounts": [
      {
        "title": "XYZ Corp (111)",
        "accountName": "XYZ Corp",
        "accountNumber": "111",
        "transactions": [
          {
            "date": "21 Jun 2016",
            "name": "gas",
            "price": "17.50"
          },
          {
            "date": "12 May 2016",
            "name": "shopping",
            "price": "111.99"
          },
          {
            "date": "30 Apr 2016",
            "name": "movies",
            "price": "7.50"
          }
        ]
      },
      {
        "title": "ABC Corp (222)",
        "accountName": "ABC Corp",
        "accountNumber": "222",
        "transactions": [
          {
            "date": "2 Jun 2016",
            "name": "coffee",
            "price": "3.25"
          },
          {
            "date": "21 May 2016",
            "name": "tea",
            "price": "1.90"
          },
          {
            "date": "20 Apr 2016",
            "name": "juice",
            "price": "4.50"
          }
        ]
      }
    ]
  }
}

Main report (main.jrxml)

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.3.0.final using JasperReports Library version 6.3.0  -->
<!-- 2016-09-08T14:41:09 -->
<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="expenses_main" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="8cf0f1cb-ccad-41ba-aa8a-44abd597de54">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="expenses json data"/>
    <queryString language="json">
        <![CDATA[expenses.accounts]]>
    </queryString>
    <field name="title" class="java.lang.String">
        <fieldDescription><![CDATA[title]]></fieldDescription>
    </field>
    <field name="date" class="java.lang.String">
        <fieldDescription><![CDATA[expenses.date]]></fieldDescription>
    </field>
    <background>
        <band splitType="Stretch"/>
    </background>
    <title>
        <band height="71" splitType="Stretch">
            <staticText>
                <reportElement x="2" y="0" width="201" height="16" uuid="2e947a01-8b6b-4169-beaa-6b2dac0d4141"/>
                <text><![CDATA[Expense Report]]></text>
            </staticText>
            <subreport>
                <reportElement x="2" y="44" width="550" height="22" uuid="1d364987-9047-4660-bd58-8a2bcfc8493d"/>
                <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource()]]></dataSourceExpression>
                <subreportExpression><![CDATA["/Users/arul/JaspersoftWorkspaceV2/reports/sub1.jasper"]]></subreportExpression>
            </subreport>
            <textField>
                <reportElement x="442" y="0" width="100" height="16" uuid="1cfbe11b-4f85-4bad-9280-d8712b80a65c"/>
                <textFieldExpression><![CDATA[$F{date}]]></textFieldExpression>
            </textField>
            <staticText>
                <reportElement x="410" y="1" width="31" height="15" uuid="ee159651-5d7b-4e0e-a52a-cb71338891cc"/>
                <text><![CDATA[Date: ]]></text>
            </staticText>
        </band>
    </title>
    <detail>
        <band height="54" splitType="Stretch">
            <textField>
                <reportElement x="2" y="10" width="550" height="20" uuid="3b6e1d4b-2a58-4684-b334-396807db1169"/>
                <textFieldExpression><![CDATA["Transactions for " + $F{title}]]></textFieldExpression>
            </textField>
            <subreport>
                <reportElement x="2" y="30" width="545" height="20" uuid="10fde2aa-2b0b-4c1c-90d5-410f2fb9369b"/>
                <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("transactions")]]></dataSourceExpression>
                <subreportExpression><![CDATA["/Users/arul/JaspersoftWorkspaceV2/reports/sub2.jasper"]]></subreportExpression>
            </subreport>
        </band>
    </detail>
</jasperReport>

Subreport1 (sub1.jrxml)

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.3.0.final using JasperReports Library version 6.3.0  -->
<!-- 2016-09-08T14:43:35 -->
<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="expenses_summary" pageWidth="555" pageHeight="802" columnWidth="555" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0" uuid="d8ef4ad1-3a01-4394-a78c-17f9d95f98de">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="expenses json data"/>
    <queryString language="JSON">
        <![CDATA[expenses.accounts]]>
    </queryString>
    <field name="accountName" class="java.lang.String">
        <fieldDescription><![CDATA[accountName]]></fieldDescription>
    </field>
    <field name="accountNumber" class="java.lang.String">
        <fieldDescription><![CDATA[accountNumber]]></fieldDescription>
    </field>
    <background>
        <band splitType="Stretch"/>
    </background>
    <title>
        <band height="21">
            <staticText>
                <reportElement x="0" y="0" width="100" height="20" uuid="258b2395-7fd1-4df0-b000-e2bfd2620fab"/>
                <textElement>
                    <font isBold="true"/>
                </textElement>
                <text><![CDATA[Account Summary]]></text>
            </staticText>
        </band>
    </title>
    <columnHeader>
        <band height="21" splitType="Stretch">
            <staticText>
                <reportElement mode="Opaque" x="0" y="0" width="100" height="20" backcolor="#DBD7D7" uuid="b04ff630-de8e-4a9b-9ea0-d402d4734ae7"/>
                <box>
                    <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                </box>
                <text><![CDATA[Account Name]]></text>
            </staticText>
            <staticText>
                <reportElement mode="Opaque" x="100" y="0" width="100" height="20" backcolor="#DBD7D7" uuid="6f0d406e-8d99-4364-888c-38bc6c0fa8c6"/>
                <box>
                    <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                </box>
                <text><![CDATA[Account Number]]></text>
            </staticText>
        </band>
    </columnHeader>
    <detail>
        <band height="21" splitType="Stretch">
            <textField>
                <reportElement x="0" y="0" width="100" height="20" uuid="c140795a-02a5-4334-9c5f-dc50e8a8ff6f"/>
                <box>
                    <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                </box>
                <textFieldExpression><![CDATA[$F{accountName}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="100" y="0" width="100" height="20" uuid="ac7a5340-4c86-45d2-a932-b7b0e347a421"/>
                <box>
                    <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                </box>
                <textFieldExpression><![CDATA[$F{accountNumber}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

Subreport2 (sub2.jrxml)

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.3.0.final using JasperReports Library version 6.3.0  -->
<!-- 2016-09-08T14:43:55 -->
<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="expenses_subreport" pageWidth="555" pageHeight="802" columnWidth="555" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0" uuid="2e39bfaf-e964-4b5d-847e-6517de5718d4">
    <field name="date" class="java.lang.String"/>
    <field name="name" class="java.lang.String"/>
    <field name="price" class="java.lang.String"/>
    <background>
        <band splitType="Stretch"/>
    </background>
    <columnHeader>
        <band height="20" splitType="Stretch">
            <staticText>
                <reportElement mode="Opaque" x="0" y="0" width="100" height="20" backcolor="#DBD7D7" uuid="8e073b78-91de-4819-886a-2527d5634067"/>
                <box>
                    <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                </box>
                <textElement>
                    <font isBold="true"/>
                </textElement>
                <text><![CDATA[Date]]></text>
            </staticText>
            <staticText>
                <reportElement mode="Opaque" x="100" y="0" width="100" height="20" backcolor="#DBD7D7" uuid="e7e7d858-05eb-4fda-9ae6-d998b4a51fd8"/>
                <box>
                    <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                </box>
                <textElement>
                    <font isBold="true"/>
                </textElement>
                <text><![CDATA[Name]]></text>
            </staticText>
            <staticText>
                <reportElement mode="Opaque" x="200" y="0" width="100" height="20" backcolor="#DBD7D7" uuid="fef220d6-4f85-4fd7-8017-5b64aff64666"/>
                <box>
                    <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                </box>
                <textElement>
                    <font isBold="true"/>
                </textElement>
                <text><![CDATA[Price]]></text>
            </staticText>
        </band>
    </columnHeader>
    <detail>
        <band height="20" splitType="Stretch">
            <textField>
                <reportElement x="0" y="0" width="100" height="20" uuid="fd021427-d26c-4c9c-8c71-c9f136f11a66"/>
                <box>
                    <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                </box>
                <textFieldExpression><![CDATA[$F{date}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="100" y="0" width="100" height="20" uuid="b6cd9815-ba45-49dd-be46-60a6a835d3fd"/>
                <box>
                    <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                </box>
                <textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="200" y="0" width="100" height="20" uuid="cf3e397e-5546-4490-a88c-7211f124475e"/>
                <box>
                    <topPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <leftPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <bottomPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                    <rightPen lineWidth="1.0" lineStyle="Solid" lineColor="#000000"/>
                </box>
                <textFieldExpression><![CDATA[$F{price}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

PDF is generating using Jasper Reports 6.3.0 Java API.

import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.query.JsonQueryExecuterFactory;
import net.sf.jasperreports.engine.util.JRLoader;

import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;

public class JasperTest {
  public static void main(String[] args) throws Exception {
    JasperReport jasperReport = (JasperReport) JRLoader.loadObjectFromFile("/Users/arul/JaspersoftWorkspaceV2/reports/main.jasper");
    Map<String, Object> jasperParameters = new HashMap<String, Object>();
    jasperParameters.put(JsonQueryExecuterFactory.JSON_INPUT_STREAM, new FileInputStream("/Users/arul/JaspersoftWorkspaceV2/data/expenses.json"));
    JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, jasperParameters);
    JasperExportManager.exportReportToPdfFile(jasperPrint, "report.pdf");
  }
}

Answer:

Your are going to deep in your initial json query

<queryString language="json">
        <![CDATA[expenses.accounts]]>
</queryString>

Date is out of scope.

The solution is to stay on expenses scope

<queryString language="json">
        <![CDATA[expenses]]>
</queryString>

The subreport 1 (sub1.jasper) you will now call with subDataSource("accounts") expression

<dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("accounts")]]></dataSourceExpression>

However you will now have only 1 detail band record (expenses), to solve this issue you can introduce another subreport.

Instead of directly calling sub report 2 introduce a subreport 1_2 (sub1_2.jasper) to iterate again on accounts subDataSource("accounts"), this will display the title and include your subreport 2 (sub2.jasper) with the datasource on transaction .subDataSource("transactions")


Main report (main.jrxml)

<?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="expenses_main" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="8cf0f1cb-ccad-41ba-aa8a-44abd597de54">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="Json"/>
    <queryString language="json">
        <![CDATA[expenses]]>
    </queryString>
    <field name="date" class="java.lang.String">
        <fieldDescription><![CDATA[date]]></fieldDescription>
    </field>
    <background>
        <band splitType="Stretch"/>
    </background>
    <title>
        <band height="71" splitType="Stretch">
            <staticText>
                <reportElement x="2" y="0" width="201" height="16" uuid="2e947a01-8b6b-4169-beaa-6b2dac0d4141"/>
                <text><![CDATA[Expense Report]]></text>
            </staticText>
            <subreport>
                <reportElement x="2" y="44" width="550" height="22" uuid="1d364987-9047-4660-bd58-8a2bcfc8493d"/>
                <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("accounts")]]></dataSourceExpression>
                <subreportExpression><![CDATA["sub1.jasper"]]></subreportExpression>
            </subreport>
            <textField>
                <reportElement x="442" y="0" width="100" height="16" uuid="1cfbe11b-4f85-4bad-9280-d8712b80a65c"/>
                <textFieldExpression><![CDATA[$F{date}]]></textFieldExpression>
            </textField>
            <staticText>
                <reportElement x="410" y="1" width="31" height="15" uuid="ee159651-5d7b-4e0e-a52a-cb71338891cc"/>
                <text><![CDATA[Date: ]]></text>
            </staticText>
        </band>
    </title>
    <detail>
        <band height="36" splitType="Stretch">
            <subreport isUsingCache="false">
                <reportElement x="2" y="10" width="545" height="20" uuid="10fde2aa-2b0b-4c1c-90d5-410f2fb9369b"/>
                <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("accounts")]]></dataSourceExpression>
                <subreportExpression><![CDATA["sub1_2.jasper"]]></subreportExpression>
            </subreport>
        </band>
    </detail>
</jasperReport>

Sub report 1_2 (sub1_2.jasper)

<?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="expenses_subreport" pageWidth="555" pageHeight="802" columnWidth="555" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0" uuid="2e39bfaf-e964-4b5d-847e-6517de5718d4">
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="Json"/>
    <field name="title" class="java.lang.String"/>
    <background>
        <band splitType="Stretch"/>
    </background>
    <detail>
        <band height="40" splitType="Stretch">
            <property name="com.jaspersoft.studio.unit.height" value="pixel"/>
            <textField>
                <reportElement x="2" y="1" width="550" height="20" uuid="934d546e-aeeb-4760-b100-cbefed73c420"/>
                <textFieldExpression><![CDATA["Transactions for " + $F{title}]]></textFieldExpression>
            </textField>
            <subreport isUsingCache="false">
                <reportElement x="5" y="16" width="545" height="20" uuid="1b8b0487-9dfa-4b82-bfb1-13009cb74ece"/>
                <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("transactions")]]></dataSourceExpression>
                <subreportExpression><![CDATA["sub2.jasper"]]></subreportExpression>
            </subreport>
        </band>
    </detail>
</jasperReport>

Sub report 1 and 2 (sub1.jrxml and sub2.jrxml)

No changes


Result

Question:

I have the following json generated by a endpoint:

{
    "data":
    {
        "id":"2",
        "type":"mytype",
        "attributes":
        {
            "header":
            {
                "name": "Name",
                "code": "Code"
            },
            "dataset": [
                {}]
        },
        "links":{"self":"http://localhost:1025/"}
    }
}

I use a JSONAdapter and query the "dataset" attribute do fill my report. It works fine. But i want to add a page header that uses the "headers" part of the json response.

Is there a way of doing that without have the pass those informations via parameters?


Answer:

If you are willing to switch to JSONQL, this is easily doable.

Considering this sample json:

{
    "headers": {
        "name": "Bla bla bla",
        "date": "2016-01-01"
    },
    "dataset": [
        {
            "id": 1,
            "val": 11
        },
        {
            "id": 2,
            "val": 22
        }
    ]
}

This would be the relevant JRXML fragment, if you want to access the 'headers.name' in a 'static' fashion:

<queryString language="jsonql">
    <![CDATA[dataset]]>
</queryString>
<field name="Name" class="java.lang.String">
    <property name="net.sf.jasperreports.jsonql.field.expression" value="$.headers.name"/>
</field>
<field name="Id" class="java.lang.String">
    <property name="net.sf.jasperreports.jsonql.field.expression" value="id"/>
</field>
<field name="Val" class="java.lang.String">
    <property name="net.sf.jasperreports.jsonql.field.expression" value="val"/>
</field>

If you want to access the 'headers.name' from the current iteration you need to have this for the Name field:

<field name="Name" class="java.lang.String">
    <property name="net.sf.jasperreports.jsonql.field.expression" value="^{2}.headers.name"/>
</field>

In essence it translates to: navigate up the tree twice and then select 'headers.name'

Question:

I want to create a JSON Object from the JASPER Report by writing Java Code. is there is any way to do this??


Answer:

Yes, is is possible. Take a look to JasperReports documentation here. Note that the JSON output format organizes data hierachically in a tree structure, written in accordance with the JSON syntax:

  • arrays are enclosed in square brackets
  • objects in arrays are comma-separated
  • objects are enclosed in curly braces
  • object members come in name:value pairs, separated by commas

Here is another topic that may help you (with screenshots).

Question:

I am running a Jasper report using JasperStarter from the command line, using the process (pr) command. The version of JasperStarter is 3.1.0, which when typing jasperstarter --help shows that there is a --json-query option. The only documentation I can find is this:

http://jasperstarter.cenote.de/usage.html#The_command_process_pr

which is for 3.0.0 (and doesn't have the --json-query option).

I need to provide a JSON file as the data source for the report, but cannot see how this is done. I have tried the following without success:

jasperstarter.exe pr -f pdf -o MyReportName MyReportTemplate --json-query MyJson.json

How can I tell JasperStarter to use a JSON file as the data source?


Answer:

This is what works for me with the JasperStarter 3.1.0 binaries:

jasperstarter.exe pr -t json --json-query "Northwind.Customers" --data-file northwind.json -f pdf -o ReportOutput JsonCustomersReport.jrxml

I have placed JsonCustomersReport.jrxml and northwind.json in the same folder where I am running the command.

The JsonCustomersReport.jrxml is a modified version of the one from the JasperReports jsondatasource sample(I have removed the property specifying the JSON file, the query string and the subreport declaration):

<?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="JsonCustomersReport" pageWidth="595" pageHeight="842" columnWidth="515" leftMargin="40" rightMargin="40" topMargin="50" bottomMargin="50" uuid="bbe115b5-a5a0-4b39-9b73-7092dc59ab6d">
    <style name="Sans_Normal" isDefault="true" fontName="DejaVu Sans" fontSize="12" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false"/>
    <style name="Sans_Bold" fontName="DejaVu Sans" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false"/>
    <style name="Sans_Italic" fontName="DejaVu Sans" fontSize="12" isBold="false" isItalic="true" isUnderline="false" isStrikeThrough="false"/>
    <field name="CustomerID" class="java.lang.String">
        <property name="net.sf.jasperreports.json.field.expression" value="CustomerID"/>
    </field>
    <field name="CompanyName" class="java.lang.String">
        <property name="net.sf.jasperreports.json.field.expression" value="CompanyName"/>
    </field>
    <title>
        <band height="50">
            <line>
                <reportElement x="0" y="0" width="515" height="1" uuid="fc148b4e-50df-4a12-aa14-8505a4cfa6e1"/>
            </line>
            <staticText>
                <reportElement style="Sans_Normal" x="0" y="10" width="515" height="30" uuid="5bf7651c-cd6b-4eaf-b65a-1413d60faab0"/>
                <textElement textAlignment="Center">
                    <font size="22"/>
                </textElement>
                <text><![CDATA[Customer Orders Report]]></text>
            </staticText>
        </band>
    </title>
    <pageHeader>
        <band height="21">
            <staticText>
                <reportElement style="Sans_Bold" mode="Opaque" x="0" y="5" width="515" height="15" forecolor="#FFFFFF" backcolor="#333333" uuid="da0f1cad-f552-424b-bf19-b41cabbfa4ac"/>
                <text><![CDATA[Customer Order List]]></text>
            </staticText>
        </band>
    </pageHeader>
    <detail>
        <band height="50">
            <textField>
                <reportElement style="Sans_Bold" x="5" y="5" width="100" height="15" isPrintWhenDetailOverflows="true" uuid="0aaeed6e-7ba1-4ab9-be59-d6ca702995fc"/>
                <textFieldExpression><![CDATA[$F{CustomerID}]]></textFieldExpression>
            </textField>
            <staticText>
                <reportElement style="Sans_Bold" isPrintRepeatedValues="false" x="404" y="5" width="100" height="15" isPrintWhenDetailOverflows="true" uuid="68e08f51-8c24-4c85-95f3-616e40c8ddab"/>
                <text><![CDATA[(continued)]]></text>
            </staticText>
            <line>
                <reportElement x="0" y="20" width="515" height="1" isPrintWhenDetailOverflows="true" uuid="6d76c22c-329f-4e77-a886-8580d3cb6bc1"/>
            </line>
            <textField>
                <reportElement style="Sans_Bold" x="109" y="5" width="291" height="15" isPrintWhenDetailOverflows="true" uuid="9a4a0a5d-4b75-4d2b-a647-aa495101df48"/>
                <textFieldExpression><![CDATA[$F{CompanyName}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
    <pageFooter>
        <band height="40">
            <line>
                <reportElement x="0" y="10" width="515" height="1" uuid="1371178a-a590-4616-affe-a4e1a24bcc84"/>
            </line>
            <textField>
                <reportElement x="200" y="20" width="80" height="15" uuid="3eb302d8-0855-4f82-a666-3c9628dce372"/>
                <textElement textAlignment="Right"/>
                <textFieldExpression><![CDATA["Page " + String.valueOf($V{PAGE_NUMBER}) + " of"]]></textFieldExpression>
            </textField>
            <textField evaluationTime="Report">
                <reportElement x="280" y="20" width="75" height="15" uuid="86f46fca-dbcb-4a60-b2f7-f8da6a4224f7"/>
                <textFieldExpression><![CDATA[" " + String.valueOf($V{PAGE_NUMBER})]]></textFieldExpression>
            </textField>
        </band>
    </pageFooter>
</jasperReport>

The northwind.json is also the one from the JasperReports jsondatasource sample.

Question:

I am testing JasperReports with JSON data and running into a problem where null values are being displayed when generated from within a Java application. Here is what I have done so far:

In Studio, I created a report that uses the JSON File data provider using a file containing the following JSON:

{
    "employees": [
        {
            "fullname":"John Stark",
            "employeeid":"29388282773",
            "phone":"415-293-2928"
        },
        {
            "fullname":"Mike Goodmann",
            "employeeid":"2938828282",
            "phone":"415-293-2726"
        },
        {
            "fullname":"David Simpson",
            "employeeid":"2938822837",
            "phone":"415-293-9826"
        },
        {
            "fullname":"Chris Humpty",
            "employeeid":"2938275452",
            "phone":"415-293-1122"
        }
    ]
}

Here is the resulting jrxml file:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 7.1.0.final using JasperReports Library version 6.4.3  -->
<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="testreport" pageWidth="792" pageHeight="612" orientation="Landscape" columnWidth="752" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" >
    <property name="com.jaspersoft.studio.data.defaultdataadapter" value="testdata"/>
    <queryString language="json">
        <![CDATA[employees]]>
    </queryString>
    <field name="fullname" class="java.lang.String">
        <property name="net.sf.jasperreports.json.field.expression" value="fullname"/>
        <fieldDescription><![CDATA[fullname]]></fieldDescription>
    </field>
    <field name="employeeid" class="java.lang.Long">
        <property name="net.sf.jasperreports.json.field.expression" value="employeeid"/>
        <fieldDescription><![CDATA[employeeid]]></fieldDescription>
    </field>
    <field name="phone" class="java.lang.String">
        <property name="net.sf.jasperreports.json.field.expression" value="phone"/>
        <fieldDescription><![CDATA[phone]]></fieldDescription>
    </field>
    <title>
        <band height="79" splitType="Stretch">
            <staticText>
                <reportElement x="240" y="24" width="280" height="30" />
                <text><![CDATA[Employee List]]></text>
            </staticText>
        </band>
    </title>
    <columnHeader>
        <band height="65" splitType="Stretch">
            <staticText>
                <reportElement x="30" y="30" width="180" height="30" />
                <text><![CDATA[Full Name]]></text>
            </staticText>
            <staticText>
                <reportElement x="240" y="30" width="160" height="30" />
                <text><![CDATA[Employee Id]]></text>
            </staticText>
            <staticText>
                <reportElement x="430" y="30" width="180" height="30" />
                <text><![CDATA[Phone Number]]></text>
            </staticText>
            <staticText>
                <reportElement x="299" y="0" width="100" height="30" />
                <text><![CDATA[employeeid]]></text>
            </staticText>
            <staticText>
                <reportElement x="468" y="0" width="100" height="30" />
                <text><![CDATA[phone]]></text>
            </staticText>
        </band>
    </columnHeader>
    <detail>
        <band height="24" splitType="Stretch">
            <textField>
                <reportElement x="30" y="0" width="180" height="20" />
                <textFieldExpression><![CDATA[$F{fullname}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="241" y="0" width="159" height="20" />
                <textFieldExpression><![CDATA[$F{employeeid}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="430" y="0" width="180" height="20" />
                <textFieldExpression><![CDATA[$F{phone}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

Then wrote a simple console app to generate the report in PDF but I get one row with NULL values. You will notice that I embedded the JSON into the class to simplify the test code until I get it to run correctly, and that I am indeed passing the JSON data into the "JasperFillManager.fillReport()" call. Here is my Java code:

public class ReportTester {
    String jsonData = "{\n" +
            "    \"employees\": [\n" +
            "        {\n" +
            "            \"fullname\":\"John Stark\",\n" +
            "            \"employeeid\":\"29388282773\",\n" +
            "            \"phone\":\"415-293-2928\"\n" +
            "        },\n" +
            "        {\n" +
            "            \"fullname\":\"Mike Goodmann\",\n" +
            "            \"employeeid\":\"2938828282\",\n" +
            "            \"phone\":\"415-293-2726\"\n" +
            "        },\n" +
            "        {\n" +
            "            \"fullname\":\"David Simpson\",\n" +
            "            \"employeeid\":\"2938822837\",\n" +
            "            \"phone\":\"415-293-9826\"\n" +
            "        },\n" +
            "        {\n" +
            "            \"fullname\":\"Chris Humpty\",\n" +
            "            \"employeeid\":\"2938275452\",\n" +
            "            \"phone\":\"415-293-1122\"\n" +
            "        }\n" +
            "    ]\n" +
            "}";
    String reportFile = "/testreport.jrxml";
    String outputPdf = "testreport.pdf";
    JasperReport jasperReport;

    public void printme() {
        try {
            InputStream employeeReportStream = getClass().getResourceAsStream(reportFile);
            jasperReport = JasperCompileManager.compileReport(employeeReportStream);

            ByteArrayInputStream jsonDataStream = new ByteArrayInputStream(jsonData.getBytes());
            JsonDataSource ds = new JsonDataSource(jsonDataStream);
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<String, Object>(), ds);

            JRPdfExporter exporter = new JRPdfExporter();
            exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
            exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(outputPdf));
            SimplePdfReportConfiguration reportConfig = new SimplePdfReportConfiguration();
            reportConfig.setSizePageToContent(true);
            reportConfig.setForceLineBreakPolicy(false);
            exporter.setConfiguration(reportConfig);

            exporter.exportReport();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Can anyone help point out what is wrong with this and why the report does not generate with data?


Answer:

What is wrong

You did not select data right. It means that JR engine prepared wrong input data for the report.

How to fix

All you need is to pass expression to the JsonDataSource instance for selecting right data.

Example:

JasperReport jasperReport;
try {
    try (InputStream inputStream = getClass().getResourceAsStream(reportTemplate)) {
        jasperReport = JasperCompileManager.compileReport(inputStream);
    }

    File outputFile = new File(outputFileName);
    SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
    ByteArrayInputStream jsonDataStream = new ByteArrayInputStream(jsonData.getBytes());
    JsonDataSource ds = new JsonDataSource(jsonDataStream, "employees");
    JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, Maps.newHashMap(), ds);

    try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         OutputStream fileOutputStream = new FileOutputStream(outputFile)) {
        JRPdfExporter exporter = new JRPdfExporter();

        exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
        exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(byteArrayOutputStream));
        exporter.setConfiguration(configuration);
        exporter.exportReport();
        byteArrayOutputStream.writeTo(fileOutputStream);
    }
} catch (IOException | JRException e) {
    throw new RuntimeException("Failed to build report", e);
}

All magic is here:

JsonDataSource ds = new JsonDataSource(jsonDataStream, "employees");

With help of expression employees we are selecting all nodes. You are doing the same at template or at data adapter at JSS.

We can view the source code of JsonDataSource class. We need moveFirst method.

@Override
public void moveFirst() throws JRException {
    if (jsonTree == null || jsonTree.isMissingNode()) {
        throw 
            new JRException(
                EXCEPTION_MESSAGE_KEY_NO_DATA,
                (Object[])null);
    }

    currentJsonNode = null;
    JsonNode result = getJsonData(jsonTree, selectExpression);
    if (result != null && result.isObject()) {
        final List<JsonNode> list = new ArrayList<JsonNode>();
        list.add(result);
        jsonNodesIterator = new Iterator<JsonNode>() {
            private int count = -1;
            @Override
            public void remove() {
                list.remove(count);
            }

            @Override
            public JsonNode next() {
                count ++;
                return list.get(count);
            }

            @Override
            public boolean hasNext() {
                return count < list.size()-1;
            }
        };
    } else if (result != null && result.isArray()) {
        jsonNodesIterator = result.elements();
    }
}

In case selecting data with employees expression we have list of "employee" entities having fullname, employeeid and phone attributes.

With help of debugging tool we can view the data at this line of code: JsonNode result = getJsonData(jsonTree, selectExpression);

In case using your code: ByteArrayInputStream jsonDataStream = new ByteArrayInputStream(jsonData.getBytes()); the data will be: