Create Jasper Report PDF form from JSON Object or JSON String

Viewed 35962

It is fine when create the Jasper report(PDF, Excel, Csv) by using JRBeanCollectionDataSource. It means that the .jrxml file accepts the collection of pojo as a input to process the report.

Now, I have been trying to create the jasper report with the same .jrxml but from JSON Object. I tried the following, but all values are null in pdf report

Resource resource = new ClassPathXmlApplicationContext().getResource("classpath:reports/project.jrxml");
JsonDataSource ds = new JsonDataSource(new File("c:\myjson.json"));
jasperDesign = JRXmlLoader.load(resource.getInputStream());
JasperReport jasperReport  = JasperCompileManager.compileReport(jasperDesign);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport,  parameters,  ds);
JasperExportManager.exportReportToPdfFile(jasperPrint, destination+fileName+".pdf");

Can any one help me?

3 Answers

This is how I handle json arrays in jasper

Lets say I want to report off the following array.

[
  {"name":"Jerry", "value":"Jesus"},
  {"name":"Gideon", "value": "Loves"},
  {"name":"Eva", "value": "You"}
]

When designing the report, make sure you name the fields the exact same name as your json field name. So in the designer I would add two fields called name and value. You can even add as many parameters to the report designer as needed. For this example, I will add a parameter called title in Jasper Studio.

Now here is the java code that will create the jasper report based off of this test array. I will hard code the json data in the code, but you can load from file or whatever you feel is best. I commented the code to explain what is happening.

import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
import net.sf.jasperreports.engine.export.JRHtmlExporter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.data.JsonDataSource;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperPrint;
import org.apache.commons.codec.binary.Base64;
import java.util.HashMap;
import java.util.Locale;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.io.*;

//Class Name. This must match the class name you put in your build.gradle file
public class JasperPDFExample {
 public static void main(String[] args) {
  try {
   try {
    //Our json object. This can be loaded from file
    String rawJsonData = "[{\"name\":\"Jerry\", \"value\":\"Jesus\"},"
                       + "{\"name\":\"Gideon\", \"value\": \"Loves\"},"
                       + "{\"name\":\"Eva\", \"value\": \"You\"}"
                       + "]";
    //Load compiled jasper report that we created on first section.
    JasperReport report = (JasperReport) JRLoader.loadObject(new File("/home/jerry/Sample.jasper"));
    //Convert json string to byte array.
    ByteArrayInputStream jsonDataStream = new ByteArrayInputStream(rawJsonData.getBytes());
    //Create json datasource from json stream
    JsonDataSource ds = new JsonDataSource(jsonDataStream);
    //Create HashMap to add report parameters
    Map parameters = new HashMap();
    //Add title parameter. Make sure the key is same name as what you named the parameter in jasper report.
    parameters.put("title", "Jasper PDF Example");
    //Create Jasper Print object passing report, parameter json data source.
    JasperPrint jasperPrint = JasperFillManager.fillReport(report, parameters, ds);
    //Export and save pdf to file
    JasperExportManager.exportReportToPdfFile(jasperPrint,"/home/jerry/jasperpdfexample.pdf");
   } catch (JRException ex) {
    ex.printStackTrace();
    throw new RuntimeException(ex);
   } catch (Exception ex) {
    ex.printStackTrace();
    throw new RuntimeException(ex);
   }
  } catch (Exception ex) {
   ex.printStackTrace();
   throw new RuntimeException(ex);
  }
 }
}

Thanks to https://mis.io/pub/how-to-create-a-jasper-pdf-report-from-a-json-datasource-in-java/ I was able to get this to work along with setting up java for jasper using gradle build tool.

You shoot yourself in the foot if you do it in Java.

A Groovy example is much more easy:

@Grab(group='net.sf.jasperreports', module='jasperreports', version='6.17.0')

import net.sf.jasperreports.engine.JasperCompileManager
import net.sf.jasperreports.engine.JasperFillManager
import net.sf.jasperreports.engine.JasperExportManager
import net.sf.jasperreports.engine.data.JsonDataSource

def xmlFile = "report.xml"
def jrReport = JasperCompileManager.compileReport(xmlFile)

def url = 'https://jsonplaceholder.typicode.com/users'
def is = new URL(url).openStream()
def ds = new JsonDataSource(is)

def params = [:]
def jrPrint = JasperFillManager.fillReport(jrReport, params, ds)

JasperExportManager.exportReportToPdfFile(jrPrint, "report.pdf")

Report template:

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
        "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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" topMargin="20" bottomMargin="20">

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

    <field name="id" class="java.lang.Long"/>
    <field name="name"/>
    <field name="username"/>

    <detail>
        <band height="15">

            <textField>
                <reportElement x="0" y="0" width="50" height="15"/>
                <textElement textAlignment="Right" verticalAlignment="Middle"/>
                <textFieldExpression class="java.lang.Long">
                    <![CDATA[$F{id}]]>
                </textFieldExpression>
            </textField>

            <textField>
                <reportElement x="70" y="0" width="100" height="15" />

                <textElement textAlignment="Left" verticalAlignment="Middle"/>
                <textFieldExpression>
                    <![CDATA[$F{name}]]>
                </textFieldExpression>
            </textField>

            <textField>
                <reportElement x="190" y="0" width="100" height="15" />
                <textElement textAlignment="Right" verticalAlignment="Middle"/>
                <textFieldExpression>
                    <![CDATA[$F{username}]]>
                </textFieldExpression>
            </textField>

        </band>
    </detail>

</jasperReport>

In the example, we get data from the popular API test website https://jsonplaceholder.typicode.com/users and pick three fields to be displayed in our report.

run with $ groovy report.gvy

Related