jackson-spreadsheet-examples

May 5, 2026 · View on GitHub

Example project for jackson-dataformat-spreadsheet — a lightweight Java library to read and write Excel files (XLSX, XLS) directly to/from Java objects.

An alternative to writing verbose Apache POI Sheet/Row/Cell code. If you know Jackson, you already know how to use this.

Why jackson-dataformat-spreadsheet?

Jackson SpreadsheetApache POI (direct)EasyExcel
Lines to read/write Excel2-320+3-5
Learning curveLow (Jackson annotations)Steep (Sheet/Row/Cell API)Low
Memory at 100K rows~128MB (streaming default)~500MB+ (XSSF)~200MB
Jackson ecosystemNative (@JsonView, @JsonIgnore, custom serializers)NoneLimited
Spring Boot integrationBuilt-in (OutputStream/InputStream)ManualEasy
Template populationYes (via POI Sheet)YesYes

Key advantages:

  • Annotation-driven mapping — no manual cell iteration
  • Streaming by default — handles 100K+ rows without OutOfMemoryError
  • Full Jackson feature set — @JsonView, @JsonUnwrapped, MixIn, custom serializers all work
  • Falls back to POI when needed — multi-sheet, formulas, charts, templates

5-Minute Quick Start

1. Add dependency

implementation("io.github.scndry:jackson-dataformat-spreadsheet:1.6.0")

2. Define your model

@Data @DataGrid
public class Product {
    private String name;
    private int quantity;
    private double price;
}

3. Write and read Excel

var mapper = new SpreadsheetMapper();

// Export to Excel
mapper.writeValue(new File("products.xlsx"), products, Product.class);

// Import from Excel
List<Product> data = mapper.readValues(new File("products.xlsx"), Product.class);

All examples are runnable as JUnit tests: ./gradlew test

Examples

Quick Start

ExampleDescription
SimpleWriteExampleExport Java objects to Excel in one line
SimpleReadExampleImport Excel to Java objects in one line

Read — Import Excel Data

ExampleDescription
BasicReadExampleImport all rows or first row into typed objects
MultiSheetReadExampleRead from specific sheet by name or index
StreamingReadExampleStream large files row-by-row (100K+ rows, constant memory)
DateHandlingExampleAutomatic date conversion (LocalDate, LocalDateTime, Date)
ErrorHandlingExampleSkip invalid rows, log errors with row location

Write — Export Excel Data

ExampleDescription
BasicWriteExampleExport to file, OutputStream, named sheet, byte array
StyleWriteExampleNumber formats, fonts, borders, fills, header styles
MergeWriteExampleVertical cell merging with nested lists
SequenceWriteExampleStream rows incrementally (database cursors, pagination)
HeaderCommentExampleAttach hover comments to header cells via @DataColumn(comment = ...)

Nested Objects

ExampleDescription
NestedObjectExampleFlatten nested POJOs to columns, reconstruct on read

Jackson Annotations

ExampleDescription
JacksonAnnotationExample@JsonProperty, @JsonIgnore, @JsonPropertyOrder, enum mapping
JsonViewExampleExport different column subsets per audience
MixInExampleExport third-party classes without modifying source
JsonUnwrappedExampleFlatten nested objects with leaf field names as headers
CustomSerializerExampleCustom cell value conversion (Yes/No booleans)
NullHandlingExample@JsonInclude(NON_NULL) — blank cells for null fields

Format Interop (CSV ↔ XLSX)

Compose SpreadsheetMapper with Jackson's CsvMapper — same POJO, two formats.

ExampleDescription
Xlsx2CsvExampleXLSX → CSV (load all rows into memory)
StreamingXlsx2CsvExampleXLSX → CSV (constant memory, row-by-row streaming)
Csv2XlsxExampleCSV → XLSX (load all rows into memory)
StreamingCsv2XlsxExampleCSV → XLSX (constant memory, row-by-row streaming)

Styling

ExampleDescription
SimpleStylesExampleOne-line type-based formatting (StylesBuilder.simple())
CloneStyleExampleInherit and extend cell styles

Sheet-Level Features

ExampleDescription
ConditionalFormattingExampleHighlight cells whose value matches a rule (column + style by name)
ConditionalFormattingColumnRefExampleSchema-aware row-relative column reference (e.g., price > minPrice per row)
ConditionalFormattingFormulaExampleRaw Excel formula passthrough — reference a config cell outside the data grid (POI integration)
ConditionalFormattingExpressionExampleArbitrary boolean Excel formula for cross-column logic (AND, OR, ISBLANK)
ConditionalFormattingColorScaleExample3-color gradient visualization across a column's value range
ConditionalFormattingRangeExamplebetween / notBetween range comparison
ConditionalFormattingDateExampleDate type comparison (LocalDate auto-converts to Excel DATE() formula)
FreezePaneExampleKeep header row visible while scrolling
AutoFilterExampleEnable Excel's filter dropdown on the header row

Configuration

ExampleDescription
ConfigurationExampleOrigin, header, column reordering, blank row handling

Apache POI Integration

ExampleDescription
POIIntegrationExampleMulti-sheet workbook, formulas, direct Sheet read
TemplateWriteExamplePopulate pre-formatted Excel templates

Spring Boot (Web)

ExampleDescription
ExcelControllerREST API for Excel download and upload

Large Files & Performance

ExampleDescription
LargeFileExample100K+ rows, file-backed shared strings, encrypted store, POI fallback

Troubleshooting

Header row not found — First row must contain column headers matching field names. Use @DataColumn("Header Name") to override, or useHeader(false) if there is no header.

OutOfMemoryError on large files — Use StreamingReadExample for reads (row-by-row iteration). For writes, enable FILE_BACKED_SHARED_STRINGS (see LargeFileExample).

Column order mismatch — Enable columnReordering(true) to match columns by header name instead of position. Or use @JsonPropertyOrder to control output order.

Dates appear as numbers — Use StylesBuilder.simple() to auto-format date columns, or apply a custom date format via @DataColumn(style = "date").

"No @DataGrid annotation found" — The root POJO must be annotated with @DataGrid. This is what tells the mapper which class defines the spreadsheet schema.

Formula cells return the cached computed value — The reader binds the cached value (emitted when the formula was last evaluated by Excel/POI). To force re-evaluation, open the workbook with POI directly and invoke FormulaEvaluator.evaluateAll() before passing the Sheet to the mapper (see POIIntegrationExample).

ClassNotFoundException: org.h2.mvstore.MVStoreFILE_BACKED_SHARED_STRINGS requires H2 on the classpath. Add the dependency:

implementation("com.h2database:h2:2.2.224")

Visual Fixture Review (maintainers)

./gradlew visualFixtures regenerates XLSX from each example and renders to PNG in build/visual-fixtures/ for visual review. Requires LibreOffice locally (brew install --cask libreoffice); the PNG step is skipped if soffice is not installed.

Limited to cell-embedded visuals (fill, font, border, format, merge). View-state features (autoFilter dropdown, freeze pane split) and width-dependent visuals don't render cleanly in headless PNG and rely on POI-based tests instead.

Requirements

License

Apache License 2.0


Anonymous, aggregated usage tracking via Scarf. No personal information is collected.