Writing JSON files
Start by importing scalaql
:
import scalaql._
// Docs classes
import scalaql.docs.Hogwarts._
import scalaql.docs.DocUtils._
// Imports for examples
import java.nio.file.Paths
import io.circe.generic.auto._
Basic writeβ
In this example, we'll read an existing JSON file, process it and write the result into a new CSV file.
Input file:
val studentsPath = Paths.get("docs/src/main/resources/students.json")
// studentsPath: java.nio.file.Path = docs/src/main/resources/students.json
printFile(studentsPath)
// {"name":"Harry","age":19,"faculty":"Gryffindor","grade":85.1,"specialization":"learning","birthDay":"1980-07-31"}
// {"name":"Ron","age":18,"faculty":"Gryffindor","grade":66.2,"specialization":"eating","birthDay":"1980-05-01"}
// {"name":"Hermione","age":18,"faculty":"Gryffindor","grade":99.6,"specialization":"learning","birthDay":"1979-09-17"}
// {"name":"Draco","age":18,"faculty":"Slytherin","grade":85.1,"specialization":"trolling","birthDay":"1980-06-05"}
// {"name":"Cedric","age":17,"faculty":"Hufflepuff","grade":90.1,"specialization":"young dying","birthDay":"1977-10-01"}
First, define an aggregation Query
:
case class FacultyInfo(
name: String,
avgAge: Double,
totalGrade: Double)
val aggregation: Query[From[Student], FacultyInfo] =
select[Student]
.groupBy(_.faculty)
.aggregate((faculty, students) =>
(
students.avgBy(_.age.toDouble) &&
students.sumBy(_.grade)
).map{ case (avgAge, totalGrade) => FacultyInfo(faculty, avgAge, totalGrade) }
)
// aggregation: Query[From[Student], FacultyInfo] = FROM(Hogwarts::Student) -> GROUP BY(String) -> AGGREGATE(MdocSession::App::FacultyInfo)
Then you could write the result into a CSV file as follows:
val outPath = Paths.get("docs/target/stats.json")
// outPath: java.nio.file.Path = docs/target/stats.json
aggregation
.foreach(
json.write[FacultyInfo].file(outPath)
)
.run(
from(
json.read[Student].file(studentsPath)
)
)
It will generate a CSV file with the following content:
printFile(outPath)
// {"name":"Gryffindor","avgAge":18.333333333333332,"totalGrade":250.9}
// {"name":"Slytherin","avgAge":18.0,"totalGrade":85.1}
// {"name":"Hufflepuff","avgAge":17.0,"totalGrade":90.1}
//
Single lineβ
You could also customize the resulting JSON file format.
By default, it writes each JSON document into a separate file line.
Alternatively, you could write them into a single array.
Start with the following imports:
import scalaql._
// Docs classes
import scalaql.docs.Hogwarts._
import scalaql.docs.DocUtils._
// Imports for examples
import java.nio.file.Paths
import io.circe.generic.auto._
With the same aggregation query:
case class FacultyInfo(
name: String,
avgAge: Double,
totalGrade: Double)
val aggregation: Query[From[Student], FacultyInfo] =
select[Student]
.groupBy(_.faculty)
.aggregate((faculty, students) =>
(
students.avgBy(_.age.toDouble) &&
students.sumBy(_.grade)
).map{ case (avgAge, totalGrade) => FacultyInfo(faculty, avgAge, totalGrade) }
)
// aggregation: Query[From[Student], FacultyInfo] = FROM(Hogwarts::Student) -> GROUP BY(String) -> AGGREGATE(MdocSession::App3::FacultyInfo)
This is how to produce a JSON file with array:
val studentsPath = Paths.get("docs/src/main/resources/students.json")
// studentsPath: java.nio.file.Path = docs/src/main/resources/students.json
val outPathArray = Paths.get("docs/target/stats_array.json")
// outPathArray: java.nio.file.Path = docs/target/stats_array.json
aggregation
.foreach(
json
.write[FacultyInfo]
.option(multiline = false)
.file(outPathArray)
)
.run(
from(
json.read[Student].file(studentsPath)
)
)
It will produce the following JSON file:
printFile(outPathArray)
// [
// {
// "name" : "Gryffindor",
// "avgAge" : 18.333333333333332,
// "totalGrade" : 250.9
// },
// {
// "name" : "Slytherin",
// "avgAge" : 18.0,
// "totalGrade" : 85.1
// },
// {
// "name" : "Hufflepuff",
// "avgAge" : 17.0,
// "totalGrade" : 90.1
// }
// ]