3838import net .sf .jasperreports .engine .type .ScaleImageEnum ;
3939import net .sf .jasperreports .engine .type .StretchTypeEnum ;
4040import net .sf .jasperreports .engine .type .TextAdjustEnum ;
41+ import net .sf .jasperreports .engine .util .JRStringUtil ;
4142import net .sf .jasperreports .engine .xml .JRXmlLoader ;
4243import net .sf .jasperreports .engine .xml .JRXmlWriter ;
4344import org .apache .commons .io .IOUtils ;
@@ -254,15 +255,18 @@ public Output execute(final Input values, final ExecutionContext context) throws
254255 final Collection <Map <String , ?>> table = new ArrayList <>();
255256
256257 final String [] columnNames = jsonTable .columns ;
258+ final String [] fieldNames = toFieldNames (columnNames );
257259
258260 // this map needs to be linked so it keeps order
259261 Map <String , Class <?>> columns = new LinkedHashMap <>();
262+ Map <String , String > columnLabels = new LinkedHashMap <>();
260263 final PArray [] jsonData = jsonTable .data ;
261264 for (final PArray jsonRow : jsonData ) {
262265 context .stopIfCanceled ();
263266 final Map <String , Object > row = new HashMap <>();
264267 for (int j = 0 ; j < jsonRow .size (); j ++) {
265268 final String columnName = columnNames [j ];
269+ final String fieldName = fieldNames [j ];
266270 Object rowValue = jsonRow .get (j );
267271 if (rowValue == JSONObject .NULL ) {
268272 rowValue = null ;
@@ -275,16 +279,17 @@ public Output execute(final Input values, final ExecutionContext context) throws
275279 rowValue = tryConvert (values .clientHttpRequestFactoryProvider .get (), rowValue );
276280 }
277281 if (columns .size () < this .maxColumns && !this .excludeColumns .contains (columnName )) {
278- Class <?> columnDef = columns .get (columnName );
282+ Class <?> columnDef = columns .get (fieldName );
279283 if (columnDef == null ) {
280284 Class <?> rowValueClass = null ;
281285 if (rowValue != null ) {
282286 rowValueClass = rowValue .getClass ();
283287 }
284- columns .put (columnName , rowValueClass );
288+ columns .put (fieldName , rowValueClass );
289+ columnLabels .put (fieldName , columnName );
285290 }
286291 }
287- row .put (columnName , rowValue );
292+ row .put (fieldName , rowValue );
288293 }
289294 table .add (row );
290295 }
@@ -313,7 +318,7 @@ public Output execute(final Input values, final ExecutionContext context) throws
313318
314319 String subreport = null ;
315320 if (this .dynamic ) {
316- subreport = generateSubReport (values , columns );
321+ subreport = generateSubReport (values , columns , columnLabels );
317322 }
318323 final JRMapCollectionDataSource dataSource = new JRMapCollectionDataSource (table );
319324 return new Output (dataSource , table .size (), subreport );
@@ -341,6 +346,14 @@ private Object tryConvert(
341346
342347 private String generateSubReport (final Input input , final Map <String , Class <?>> columns )
343348 throws JRException , IOException {
349+ return generateSubReport (input , columns , new HashMap <>());
350+ }
351+
352+ private String generateSubReport (
353+ final Input input ,
354+ final Map <String , Class <?>> columns ,
355+ final Map <String , String > columnLabels )
356+ throws JRException , IOException {
344357 byte [] bytes = loadJasperTemplate (input .template .getConfiguration ());
345358 final JasperDesign templateDesign = JRXmlLoader .load (new ByteArrayInputStream (bytes ));
346359
@@ -352,7 +365,8 @@ private String generateSubReport(final Input input, final Map<String, Class<?>>
352365 final JRDesignSection detailSection = (JRDesignSection ) templateDesign .getDetailSection ();
353366 int detailHeight = detailSection .getBands ()[0 ].getHeight ();
354367
355- populateTemplateDesign (columns , templateDesign , detailSection , headerHeight , detailHeight );
368+ populateTemplateDesign (
369+ columns , columnLabels , templateDesign , detailSection , headerHeight , detailHeight );
356370
357371 final File jrxmlFile =
358372 File .createTempFile ("table-" , JASPER_REPORT_XML_FILE_EXT , input .tempTaskDirectory );
@@ -369,6 +383,7 @@ private String generateSubReport(final Input input, final Map<String, Class<?>>
369383
370384 private void populateTemplateDesign (
371385 final Map <String , Class <?>> columns ,
386+ final Map <String , String > columnLabels ,
372387 final JasperDesign templateDesign ,
373388 final JRDesignSection detailSection ,
374389 final int headerHeight ,
@@ -416,6 +431,7 @@ private void populateTemplateDesign(
416431 columnHeaderStyle = templateDesign .getStylesMap ().get (this .headerStyle );
417432 }
418433 String columnName = entry .getKey ();
434+ String columnLabel = columnLabels .getOrDefault (columnName , columnName );
419435 Class <?> valueClass = String .class ;
420436 if (entry .getValue () != null ) {
421437 valueClass = entry .getValue ();
@@ -439,7 +455,7 @@ private void populateTemplateDesign(
439455 columnWidth ,
440456 headerHeight ,
441457 columnHeaderStyle ,
442- columnName ,
458+ columnLabel ,
443459 headerBand );
444460
445461 // Add fields to the detailBand
@@ -518,7 +534,7 @@ private static void addHeaderFieldToHeaderBand(
518534 final int columnWidth ,
519535 final int headerHeight ,
520536 final JRStyle columnHeaderStyle ,
521- final String columnName ,
537+ final String columnLabel ,
522538 final JRDesignBand headerBand ) {
523539 JRDesignTextField colHeaderField = new JRDesignTextField ();
524540 colHeaderField .setX (headerPosX );
@@ -531,11 +547,23 @@ private static void addHeaderFieldToHeaderBand(
531547 colHeaderField .setStretchType (StretchTypeEnum .ELEMENT_GROUP_HEIGHT );
532548
533549 JRDesignExpression headerExpression = new JRDesignExpression ();
534- headerExpression .setText ('"' + columnName + '"' );
550+ headerExpression .setText ('"' + JRStringUtil . escapeJavaStringLiteral ( columnLabel ) + '"' );
535551 colHeaderField .setExpression (headerExpression );
536552 headerBand .addElement (colHeaderField );
537553 }
538554
555+ private String [] toFieldNames (final String [] columnNames ) {
556+ if (!this .dynamic ) {
557+ return columnNames ;
558+ }
559+
560+ final String [] result = new String [columnNames .length ];
561+ for (int i = 0 ; i < columnNames .length ; i ++) {
562+ result [i ] = "col_" + i ;
563+ }
564+ return result ;
565+ }
566+
539567 private void addTextField (
540568 final String columnName ,
541569 final JRDesignBand detailBand ,
0 commit comments