The matrix-json module provides functionality for reading JSON data into Matrix objects and writing Matrix objects to JSON format. This module is particularly useful when working with web APIs or when you need to exchange data with JavaScript applications.
To use the matrix-json module, you need to add it as a dependency to your project.
implementation 'org.apache.groovy:groovy:5.0.5'
implementation platform('se.alipsa.matrix:matrix-bom:2.5.1')
implementation 'se.alipsa.matrix:matrix-core'
implementation 'se.alipsa.matrix:matrix-json'<project>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>se.alipsa.matrix</groupId>
<artifactId>matrix-bom</artifactId>
<version>2.5.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy</artifactId>
<version>5.0.5</version>
</dependency>
<dependency>
<groupId>se.alipsa.matrix</groupId>
<artifactId>matrix-core</artifactId>
</dependency>
<dependency>
<groupId>se.alipsa.matrix</groupId>
<artifactId>matrix-json</artifactId>
</dependency>
</dependencies>
</project>Note that the matrix-json module requires JDK 21 or higher. The groovy-json dependency is no longer required since v2.2.0; matrix-json uses Jackson for both reading and writing.
The JsonWriter class provides a fluent builder API for converting Matrix objects to JSON format.
import se.alipsa.matrix.core.Matrix
import se.alipsa.matrix.json.JsonWriter
import java.time.LocalDate
import static se.alipsa.matrix.core.ListConverter.toLocalDates
// Create a Matrix with employee data
def empData = Matrix.builder().data(
emp_id: 1..3,
emp_name: ["Rick", "Dan", "Michelle"],
salary: [623.3, 515.2, 611.0],
start_date: toLocalDates("2012-01-01", "2013-09-23", "2014-11-15"))
.types(Integer, String, Number, LocalDate)
.build()
// Write to a file with pretty-printing
JsonWriter.write(empData).indent().to(new File('employees.json'))
// Or get the JSON as a string
String json = JsonWriter.write(empData).indent().asString()
println jsonThe output will be:
[
{
"emp_id": 1,
"emp_name": "Rick",
"salary": 623.3,
"start_date": "2012-01-01"
},
{
"emp_id": 2,
"emp_name": "Dan",
"salary": 515.2,
"start_date": "2013-09-23"
},
{
"emp_id": 3,
"emp_name": "Michelle",
"salary": 611.0,
"start_date": "2014-11-15"
}
]You can apply formatters to individual columns and set custom date format patterns:
import se.alipsa.matrix.json.JsonWriter
import java.time.format.DateTimeFormatter
// Custom date format for all temporal columns
String json = JsonWriter.write(empData)
.dateFormat('yy/dd/MM')
.indent()
.asString()
// Per-column formatters
String formattedJson = JsonWriter.write(empData)
.formatter('salary') { it * 10 + ' kr' }
.formatter('start_date') { DateTimeFormatter.ofPattern('yy/dd/MM').format(it) }
.indent()
.asString()
println formattedJsonThe output with column formatters will be:
[
{
"emp_id": 1,
"emp_name": "Rick",
"salary": "6233.0 kr",
"start_date": "12/01/01"
},
{
"emp_id": 2,
"emp_name": "Dan",
"salary": "5152.0 kr",
"start_date": "13/23/09"
},
{
"emp_id": 3,
"emp_name": "Michelle",
"salary": "6110.0 kr",
"start_date": "14/15/11"
}
]The builder supports multiple output targets:
import se.alipsa.matrix.json.JsonWriter
// Write to a File
JsonWriter.write(data).indent().to(new File('data.json'))
// Write to a Path
JsonWriter.write(data).to(Path.of('data.json'))
// Write to a String file path
JsonWriter.write(data).to('/path/to/data.json')
// Write directly to a Writer (streams without intermediate String)
JsonWriter.write(data).to(writer)
// Get as a String
String json = JsonWriter.write(data).asString()The JsonReader class reads JSON arrays into Matrix objects using Jackson's streaming API, which provides constant memory usage regardless of JSON size.
The JSON needs to be in the format of a list ([]) with each row represented as an object ({}):
import se.alipsa.matrix.core.Matrix
import se.alipsa.matrix.json.JsonReader
import java.time.LocalDate
// Read from a JSON string
Matrix table = JsonReader.read('''[
{"emp_id": 1, "emp_name": "Rick", "salary": 623.3, "start_date": "2012-01-01"},
{"emp_id": 2, "emp_name": "Dan", "salary": 515.2, "start_date": "2013-09-23"},
{"emp_id": 3, "emp_name": "Michelle", "salary": 611.0, "start_date": "2014-11-15"}
]''')
// Convert columns to appropriate types
Matrix typedTable = table.convert([Integer, String, Number, LocalDate])
println typedTable.content()import se.alipsa.matrix.json.JsonReader
// Read from a File (matrix name is derived from filename, e.g. "employees")
Matrix m = JsonReader.read(new File('employees.json'))
// Read from a Path
Matrix m = JsonReader.read(Path.of('data.json'))
// Read from a file path string
Matrix m = JsonReader.readFile('/path/to/data.json')
// Read from a URL
Matrix m = JsonReader.read(new URL('https://api.example.com/data.json'))
// Read from a URL string
Matrix m = JsonReader.readUrl('https://api.example.com/data.json')
// Read from an InputStream or Reader
Matrix m = JsonReader.read(inputStream)
Matrix m = JsonReader.read(reader)When using the generic Matrix.read() API, you can specify types and date format directly:
import se.alipsa.matrix.core.Matrix
import java.time.LocalDate
Matrix typed = Matrix.read(
[types: [Integer, String, Number, LocalDate], dateTimeFormat: 'yyyy-MM-dd'],
new File('employees.json')
)Nested objects are automatically flattened to dot-notation keys, and arrays use bracket notation:
Matrix m = JsonReader.read('''[
{"person": {"name": "Alice", "age": 30}, "scores": [90, 95]}
]''')
println m.columnNames() // [person.name, person.age, scores[0], scores[1]]Duplicate keys after flattening (e.g., both "a.b" as a literal key and "a": {"b": ...})
will throw an IllegalArgumentException.
The matrix-json module is useful when working with web APIs that return JSON data:
import se.alipsa.matrix.core.Matrix
import se.alipsa.matrix.json.JsonReader
// Read directly from a URL
Matrix data = JsonReader.readUrl('https://api.example.com/data.json')
// Process the data
println "Imported ${data.rowCount()} rows of data"
println data.head()-
Data Types: When reading JSON, values are imported as their JSON types (String, BigDecimal, Boolean, etc.). Use the
convertmethod or thetypesread option to convert columns to appropriate Groovy types. -
BigDecimal Precision: Since v2.1.3, JSON floating-point values are read as
BigDecimalinstead ofDouble, preserving exact text precision. -
Date Formatting: When writing dates, they are formatted using
yyyy-MM-ddby default. Use.dateFormat(pattern)on the builder for custom formats. -
Nested JSON: Nested objects and arrays are automatically flattened. For deeply nested structures, check the resulting column names after reading.
-
Memory Efficiency: Both
JsonReaderandJsonWriteruse Jackson streaming, keeping memory usage constant regardless of data size.
Go to previous section | Go to next section | Back to outline