我正在用JSON数据测试JasperReports,并遇到了一个问题,即从Java应用程序内部生成时会显示空值。这是我到目前为止所做的:
在Studio中,我创建了一个使用JSON File数据提供程序的报告,该报告使用了包含以下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"
}
]
}
这里是生成的jrxml文件:
<?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>
然后写了一个简单的控制台应用程序来生成PDF格式的报告,但我得到的行中包含NULL值。您会注意到,我将JSON嵌入到类中以简化测试代码,直到我使其正确运行为止,并且确实将JSON数据传递到“ JasperFillManager.fillReport()”调用中。这是我的Java代码:
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();
}
}
}
任何人都可以指出这是什么问题以及为什么报表不包含数据吗?
您没有选择正确的数据。这意味着JR引擎为报告准备了错误的输入数据。
您所需要做的就是将表达式传递给JsonDataSource实例以选择正确的数据。
示例:
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);
}
所有魔法都在这里:
JsonDataSource ds = new JsonDataSource(jsonDataStream, "employees");
借助表达式employees
,我们正在选择所有节点。您正在JSS的模板或数据适配器处执行相同的操作。
我们可以查看JsonDataSource
类的源代码。我们需要moveFirst方法。属性的“雇员”实体列表。借助调试工具,我们可以在以下代码行中查看数据:@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(); } }
如果选择具有
employees
表达式的数据,我们将具有具有[[全名,雇员编号和电话
JsonNode result = getJsonData(jsonTree, selectExpression);
[如果使用您的代码:ByteArrayInputStream jsonDataStream = new ByteArrayInputStream(jsonData.getBytes());
,数据将是: