JasperReports-JSON数据报告在Java中运行时显示空值

问题描述 投票:0回答:1

我正在用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();
        }
    }
}

任何人都可以指出这是什么问题以及为什么报表不包含数据吗?

java json jasper-reports
1个回答
0
投票

怎么了

您没有选择正确的数据。这意味着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);

The data of JsonNode result

[如果使用您的代码:ByteArrayInputStream jsonDataStream = new ByteArrayInputStream(jsonData.getBytes());,数据将是:

The JsonNode result without using exression

© www.soinside.com 2019 - 2024. All rights reserved.