### Compile and Run JVM Example
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jq.md
Use this command to compile the JVM version of the example using sbt-assembly and then run the resulting fat jar with a sample JSON file and a JQ-like query.
```shell
$ sbt exampleJqJVM/assembly
$ java -jar examples/jqlike/.jvm/target/scala-2.13/jq-like.jar -q '.[] | { "full_name": .name, "language": .language }' -f site/cookbooks/data/json/sample.json
```
--------------------------------
### Compile and Run Scala.js Example
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jq.md
Use this command to compile the Scala.js version of the example using sbt and then run the resulting JavaScript file with Node.js, a sample JSON file, and a JQ-like query.
```shell
$ sbt exampleJqJS/fastLinkJS
$ node examples/jqlike/.js/target/scala-2.13/jq-like-fastopt/main.js -q '.[] | { "full_name": .name, "language": .language }' -f site/cookbooks/data/json/sample.json
```
--------------------------------
### Compile and Run Scala Native Example
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jq.md
Use this command to compile the Scala Native version of the example using sbt and then run the resulting native executable with a sample JSON file and a JQ-like query.
```shell
$ sbt exampleJqNative/nativeLink
$ examples/jqlike/.native/target/scala-2.13/jq-like-out -q '.[] | { "full_name": .name, "language": .language }' -f site/cookbooks/data/json/sample.json
```
--------------------------------
### Initialize CSV Stream
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/generic.md
Sets up an input CSV string and converts it into an fs2 Stream for processing. This is a common starting point for CSV operations.
```scala
import fs2._
import fs2.data.csv._
val input = """i,s,j
1,test,2
,other,-3
""".stripMargin
val stream = Stream.emit(input).covary[Fallible]
```
--------------------------------
### Define Input Stream for JSON Parsing
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/libraries.md
Sets up a sample JSON input stream for use in subsequent examples. This stream contains two JSON objects.
```scala
import fs2.{Fallible, Stream}
import fs2.data.json._
import fs2.data.json.jsonpath._
import fs2.data.json.jsonpath.literals._
def input[F[_]] = Stream.emit("""{
"field1": 0,
"field2": "test",
"field3": [1, 2, 3]
}
{
"field1": 2,
"field3": []
}""").covary[F]
val stream = input[Fallible].through(tokens)
val sel = jsonpath"$$.field3[*]"
```
--------------------------------
### Define XML Input Stream
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/xpath.md
Example of creating an XML input stream using the xml interpolator. This sets up the data for subsequent XPath operations.
```scala
import cats.syntax.all._
import fs2._
import fs2.data.xml._
val stream = xml"""
text
"""
```
--------------------------------
### Run JSON Lines Example with Scala CLI (JVM)
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jsonlines.md
Command to execute the Scala CLI script for handling JSON Lines data on the JVM platform. It specifies the script path and the 'read' command with an input file.
```shell
scala-cli site/cookbooks/scripts/jsonlines.scala -- read site/cookbooks/data/jsonl/nested.jsonl
```
--------------------------------
### Example Test Case Verification with csv-spectrum
Source: https://github.com/gnieh/fs2-data/blob/main/csv/shared/src/test/resources/csv-spectrum/readme.md
Demonstrates how to use the loaded test data within a test suite. It logs the name of the test being run and asserts the equality of a parsed CSV to its JSON representation.
```javascript
vsr spectrum = require('csv-spectrum')
spectrum(function(err, data) {
console.log('testing ' + data[0].name)
t.equal(csv2json(data[0].csv), JSON.parse(data[0].json))
})
```
--------------------------------
### Run JSON Lines Example with Scala CLI (Native)
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jsonlines.md
Command to execute the Scala CLI script for handling JSON Lines data on the native platform. It utilizes the --native flag to target native compilation and includes the 'read' command with an input file.
```shell
scala-cli --native site/cookbooks/scripts/jsonlines.scala -- read site/cookbooks/data/jsonl/nested.jsonl
```
--------------------------------
### Run JSON Lines Example with Scala CLI (JavaScript)
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jsonlines.md
Command to execute the Scala CLI script for handling JSON Lines data on the JavaScript platform. It uses the --js flag to specify the target platform and includes the 'read' command with an input file.
```shell
scala-cli --js site/cookbooks/scripts/jsonlines.scala -- read site/cookbooks/data/jsonl/nested.jsonl
```
--------------------------------
### Read Bytes from a File
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/index.md
Illustrates how to read raw bytes from a file into an `fs2.Stream[IO, Byte]`. This is a common starting point for processing file data, especially textual formats that require decoding.
```scala
import cats.effect._
import fs2._
import fs2.io.file.{Files, Flags, Path}
Files[IO]
.readAll(Path("/some/path/to/a/file.data"), 1024, Flags.Read)
// perform your decoding, parsing, and transformation here
.compile
.drain
```
--------------------------------
### Consume and Save XML Matches with XPath
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/xpath.md
Use `filter.consumer` to handle each XML match as a stream without emitting values. This example saves each match to a file, incrementing a counter.
```scala
import fs2.io.file.{Files, Path}
def saveXml(counter: Ref[IO, Int], events: Stream[IO, XmlEvent]): Stream[IO, Nothing] =
Stream.eval(counter.getAndUpdate(_ + 1)).flatMap { index =>
events
.through(render.raw())
.through(Files[IO].writeUtf8(Path(s"match-$index.xml")))
}
val program =
for {
counter <- Ref[IO].of(0)
_ <- stream
.lift[IO]
.through(filter.consume(path, saveXml(counter, _)))
.compile
.drain
} yield ()
program.unsafeRunSync()
Files[IO].readUtf8(Path("match-0.xml")).compile.string.unsafeRunSync()
Files[IO].readUtf8(Path("match-1.xml")).compile.string.unsafeRunSync()
```
--------------------------------
### Wrap JSON Lines Stream as Top-Level Array
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jsonlines.md
Reads a JSON Lines file, processes it using `readJsonLines`, tokenizes the JSON, wraps the resulting stream into a single top-level JSON array, and then pretty-prints it. This example demonstrates reading a file and producing a formatted JSON array string.
```scala
val array =
Files[IO]
.readAll(Path("site/cookbooks/data/jsonl/nested.jsonl"))
.through(readJsonLines)
.through(fs2.data.json.ast.tokenize)
.through(fs2.data.json.wrap.asTopLevelArray)
.through(fs2.data.json.render.prettyPrint(width = 35))
array
.compile
.string
.unsafeRunSync()
```
--------------------------------
### Implement RowEncoder for Shapeless HList
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/index.md
Define a `RowEncoder` for a shapeless `HList` to encode data into CSV rows positionally. This example encodes an `Option[Int]`, a `String`, and an `Int` into a `Row`.
```scala
import shapeless._
implicit object HListEncoder extends RowEncoder[Option[Int] :: String :: Int :: HNil] {
def apply(input: Option[Int] :: String :: Int :: HNil): Row =
Row(NonEmptyList.of(CellEncoder[Option[Int]].apply(input.head), input.tail.head, input.tail.tail.head.toString))
}
// .tail drops the header line
val row = Stream(Option(3) :: "test" :: 42 :: HNil)
row.through(lowlevel.encode).compile.toList
```
--------------------------------
### Implement RowDecoder for Shapeless HList
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/index.md
Create a `RowDecoder` for a shapeless `HList` to decode CSV rows based on field positions. This example decodes an `Option[Int]`, a `String`, and an `Int` from the row.
```scala
import shapeless._
implicit object HListDecoder extends RowDecoder[Option[Int] :: String :: Int :: HNil] {
def apply(row: Row): DecoderResult[Option[Int] :: String :: Int :: HNil] =
if(row.values.size < 3)
Left(new DecoderError("row is too short"))
else
for {
i <- if(row.values.head.isEmpty) Right(None) else CellDecoder[Int].apply(row.values.head).map(Some(_))
s <- CellDecoder[String].apply(row.values.tail.head)
j <- CellDecoder[Int].apply(row.values.tail.tail.head)
} yield i :: s :: j :: HNil
}
// .tail drops the header line
val hlists = noh.tail.through(lowlevel.decode[Fallible, Option[Int] :: String :: Int :: HNil])
hlists.compile.toList
```
--------------------------------
### Define and Encode Scala Case Classes as JSON Events
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/index.md
Defines a sealed trait `Event` with case classes and provides a Circe encoder for them. This setup is necessary for generating JSON streams from these case classes.
```scala
sealed trait Event
case class CreateCounter(name: String, initialValue: Int) extends Event
case class RemoveCounter(name: String) extends Event
case class IncreaseCounter(name: String) extends Event
object Event {
import _root_.io.circe.Encoder
import _root_.io.circe.generic.extras.Configuration
import _root_.io.circe.generic.extras.semiauto._
implicit val configuration = Configuration.default.withDiscriminator("type")
implicit val encoder: Encoder[Event] = deriveConfiguredEncoder
}
```
--------------------------------
### Initialize JSON Stream
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/jq.md
Sets up an initial JSON string and converts it into a stream of tokens. Requires fs2 and fs2-data-json libraries.
```scala
import cats.effect.SyncIO
import cats.syntax.all._
import fs2._
import fs2.data.json._
val input = """
{
|"field1": 0,
|"field2": "test",
|"field3": [1, 2, 3]
|}"""
val stream = Stream.emit(input).through(tokens[SyncIO, String])
```
--------------------------------
### Initialize Pagefind UI
Source: https://github.com/gnieh/fs2-data/blob/main/site/helium/templates/mainNav.template.html
Initializes the Pagefind UI component on the DOMContentLoaded event. Configure options like showing sub-results or images.
```javascript
window.addEventListener('DOMContentLoaded', (event) => { new PagefindUI({ element: "#search", showSubResults: true, showImages: false }); });
```
--------------------------------
### Handle invalid CBOR item stream with toBinary
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/cbor/index.md
The `toBinary` pipe fails if the input stream is invalid, such as missing elements in an array. This example demonstrates such a case.
```scala
val invalid =
Stream
.emits(List(
CborItem.StartArray(3),
CborItem.TextString("an"),
CborItem.TextString("array")))
invalid
.through(toBinary[Fallible])
.compile
.drain
```
--------------------------------
### Stream indefinite arrays/maps in serialized CBOR
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/cbor/index.md
Control whether arrays or maps are streamed in the serialized form by setting the `indefinite` flag to `true`. This example demonstrates making top-level arrays streamed.
```scala
valueStream
.map {
// make top-level arrays streamed
case CborValue.Array(elements, _) => CborValue.Array(elements, true)
case value => value
}
.through(toItems)
.compile
.toList
```
--------------------------------
### Deserialize Byte Stream to MsgpackItem
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
Use the `fromBinary` pipe to convert a stream of `Byte`s into a stream of `MsgpackItem`s. This process is the inverse of serialization, excluding extension types.
```scala
val itemStream = binaryStream.through(data.msgpack.low.fromBinary[Fallible])
itemStream.compile.toList == inputStream.compile.toList
```
--------------------------------
### Define JSON Input and Token Stream
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/jsonpath.md
Sets up a multi-line JSON string and converts it into a stream of tokens using fs2-data-json. Ensure fs2 and cats-syntax are imported.
```scala
import cats.syntax.all._
import fs2._
import fs2.data.json._
val input = """
{
| "field1": 0,
| "field2": "test",
| "field3": [1, 2, 3]
|}
|{
| "field1": 2,
| "field3": []
|}"""
val stream = Stream.emit(input).through(tokens[Fallible, String])
```
--------------------------------
### Deserialization from Binary
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
The `fromBinary` pipe converts a stream of `Byte`s into a stream of `MsgpackItem`s. This is generally the inverse of the serialization process.
```APIDOC
## fromBinary
### Description
Converts a stream of `Byte`s into a stream of `MsgpackItem`s. This process is the inverse of serialization, excluding extension types.
### Method
Pipe
### Endpoint
N/A (Pipe)
### Parameters
N/A (Pipe)
### Request Example
```scala
val itemStream = binaryStream.through(data.msgpack.low.fromBinary[Fallible])
itemStream.compile.toList == inputStream.compile.toList
```
### Response
#### Success Response
- `MsgpackItem`: A stream of MessagePack items.
#### Response Example
(Stream of MsgpackItems)
```
--------------------------------
### Serialization to Binary
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
The `toBinary` pipe serializes a stream of `MsgpackItem`s into a binary stream of `Byte`s. It includes stream validation.
```APIDOC
## toBinary
### Description
Serializes a stream of `MsgpackItem`s into a binary stream of `Byte`s, performing stream validation.
### Method
Pipe
### Endpoint
N/A (Pipe)
### Parameters
N/A (Pipe)
### Request Example
```scala
import fs2.*
import fs2.data.msgpack.low.*
import scodec.bits.*
val inputStream = Stream[Fallible, MsgpackItem](
MsgpackItem.Array(2),
MsgpackItem.UnsignedInt(hex"ab"),
MsgpackItem.UnsignedInt(hex"abcdef01")
)
val binaryStream = inputStream.through(data.msgpack.low.toBinary)
```
### Response
#### Success Response
- `Byte`: A stream of bytes representing the MessagePack serialized data.
#### Response Example
(Binary stream output)
```
--------------------------------
### Unsafely Emit All Raw XML Matches with XPath
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/xpath.md
The `filter.unsafeRaw` operator emits a stream of all matches, where each match is a nested stream of XML events. These inner streams must be fully consumed to prevent memory leaks. This example processes them in parallel.
```scala
stream
.lift[IO]
.through(filter.unsafeRaw(path))
.parEvalMapUnbounded(_.through(render.raw()).compile.foldMonoid)
.compile
.toList
.unsafeRunSync()
```
--------------------------------
### Handle Optional CSV Fields
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/index.md
Provides methods like `asOptionalAt` and `asOptional` on `Row` and `CsvRow` to manage optional values. It allows customization for treating missing fields, empty strings, or specific placeholder values (like 'null') as `None`.
```scala
val testRow = CsvRow.fromNelHeaders(NonEmptyList.of("first" -> "value1", "second" -> "null"))
def get(field: String) =
testRow.asOptional[String](field, missing = _ => Right(None), isEmpty = _ == "null")
get("first")
get("second")
get("third")
```
--------------------------------
### Dealing with optional data
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/index.md
Provides methods like `asOptionalAt` and `asOptional` to handle missing, empty, or placeholder optional values in rows.
```APIDOC
## Dealing with optional data
Optional values have no unified representation in CSV. The `Row` and `Row[Header]` types provide `asOptionalAt` and `asOptional` methods to handle optional values.
By default, these methods fail if the field is missing and return `None` if the field is the empty string.
### Customizing optional value handling
Treat missing fields and specific placeholder values (like `"null"`) as `None`.
```scala
val testRow = CsvRow.fromNelHeaders(NonEmptyList.of("first" -> "value1", "second" -> "null"))
def get(field: String) =
testRow.asOptional[String](field, missing = _ => Right(None), isEmpty = _ == "null")
get("first")
get("second")
get("third")
```
```
--------------------------------
### Render JSON Stream to String (Compact)
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/index.md
Collects a JSON token stream into a single compact string. No specific imports are needed beyond the stream and renderers.
```scala
stream.through(render.compact).compile.string
```
--------------------------------
### Write JSON to File (Compact Form)
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/index.md
Use this to write a JSON token stream to a file in a compact format without spaces or newlines. Ensure `fs2.io.file.Files` and `fs2.data.json.render` are imported.
```scala
import fs2.io.file.{Files, Flags, Path}
stream
.through(render.compact)
.through(text.utf8.encode)
.lift[IO]
.through(Files[IO].writeAll(Path("/some/path/to/file.json"), Flags.Write))
.compile
.drain
```
--------------------------------
### Build JSON Selector using DSL
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/transformations.md
Constructs a JSON selector using the fs2.data.json.selector DSL. The .compile method finalizes the selector.
```scala
import fs2.data.json.selector._
val selectorFromDsl = root.field("field3").iterate.compile
```
--------------------------------
### Use XPath Interpolator
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/xpath.md
Shows how to use the xpath interpolator for creating XPath selectors. This method offers compile-time syntax checking for improved safety.
```scala
import fs2.data.xml.xpath.literals._
val path = xpath"//a"
```
--------------------------------
### Render Raw XML Event Stream to File
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/index.md
Writes a raw XML event stream to a file without formatting. The stream is encoded to UTF-8 before writing.
```scala
import fs2.io.file.{Files, Flags, Path}
stream
.through(render.raw())
.through(text.utf8.encode)
.through(Files[IO].writeAll(Path("/some/path/to/file.xml"), Flags.Write))
.compile
.drain
```
--------------------------------
### Serialize MsgpackItem Stream to Binary
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
Use the `toBinary` pipe for stream validation during serialization. This pipe ensures that malformed data is not emitted.
```scala
import fs2.*
import fs2.data.msgpack.low.*
import scodec.bits.*
val inputStream = Stream[Fallible, MsgpackItem](
MsgpackItem.Array(2),
MsgpackItem.UnsignedInt(hex"ab"),
MsgpackItem.UnsignedInt(hex"abcdef01")
)
val binaryStream = inputStream.through(data.msgpack.low.toBinary)
```
--------------------------------
### Parse Text Stream with Char Input
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/index.md
Demonstrates how to use the `tokens` pipe with a stream of `Char` to parse textual data. Ensure the appropriate `CharLikeChunks` instance is in scope.
```scala
// Stream of `Char`
Stream.emits("Some input string").through(tokens[Pure, Char])
```
--------------------------------
### Render JSON Stream to String (Pretty Print)
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/index.md
Collects a JSON token stream into a single string with indentation. The default indentation is 2 spaces and a width of 10. You can customize the indent size and width.
```scala
// default indentation is 2 spaces
stream.through(render.prettyPrint(width = 10)).compile.string
```
```scala
// if you are more into 4 spaces (or any other indentation size) you can change the indentation size
stream.through(render.prettyPrint(indent = 4, width = 10)).compile.string
```
--------------------------------
### Parse Text Stream with String Input
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/index.md
Demonstrates how to use the `tokens` pipe with a stream of `String` to parse textual data. Ensure the appropriate `CharLikeChunks` instance is in scope.
```scala
// Stream of `String`
Stream.emit("Some input string").through(tokens[Pure, String])
```
--------------------------------
### Build Lenient JSON Selector with Mandatory Field using DSL
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/transformations.md
Demonstrates building a JSON selector with a mandatory field and lenient iteration using the DSL. This allows for more flexible selection criteria.
```scala
val selectorFromDsl = root.field("field3").!.iterate.?.compile
```
--------------------------------
### Serialize a Stream of Custom Objects to MessagePack Bytes
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
Serializes a stream of User objects into a stream of MessagePack bytes using the previously defined MsgpackSerializer. Ensure the Fallible effect type is handled appropriately.
```scala
val inputStream = Stream[Fallible, User](
User("foo", 30, Instant.parse("2025-02-03T10:00:00.00Z"), List.empty),
User("bar", 31, Instant.parse("2026-01-17T10:00:00.00Z"), List(1, 3, 7))
)
val byteStream = inputStream.through(data.msgpack.high.serialize[Fallible, User])
```
--------------------------------
### Generate JSON Lines from Sample JSON Array
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jsonlines.md
Reads a sample JSON array from a file, filters the first five elements using JSONPath, processes them using `writeJsonLines` to produce JSON Lines format, and then decodes the resulting bytes back to a string. This demonstrates generating JSON Lines data from existing JSON.
```scala
import fs2.data.json.jsonpath.literals._
Files[IO]
.readAll(Path("site/cookbooks/data/json/sample.json"))
.through(fs2.text.utf8.decode)
.through(fs2.data.json.tokens)
.through(fs2.data.json.jsonpath.filter.values(jsonpath"$$[0:4]"))
.through(writeJsonLines)
.through(fs2.text.utf8.decode)
.compile
.string
.unsafeRunSync()
```
--------------------------------
### Parse JSON Input to AST with Circe
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/libraries.md
Parses the input JSON stream into an Abstract Syntax Tree (AST) using Circe integration. The resulting ASTs are then formatted with two spaces.
```scala
import fs2.data.json.circe._
val asts = input[Fallible].through(ast.parse)
asts.map(_.spaces2).compile.toList
```
--------------------------------
### Programmatic Usage of csv-spectrum
Source: https://github.com/gnieh/fs2-data/blob/main/csv/shared/src/test/resources/csv-spectrum/readme.md
Use this snippet to load all CSV test cases and their JSON counterparts. The callback receives an error object if any, and an array of test case objects.
```javascript
vsr spectrum = require('csv-spectrum')
spectrum(function(err, data) {
// data is an array of objects has all the csv and json versions of the tests
})
```
--------------------------------
### Collect AST Values from Byte Stream
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
Collects all MsgpackValue AST nodes from a byte stream into a list. This demonstrates consuming the stream of AST values.
```scala
valueStream.compile.toList
```
--------------------------------
### Serialize high-level CBOR value stream to binary
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/cbor/index.md
Serialize a high-level CBOR value stream into a binary format using the `toBinary` pipe from the `fs2.data.cbor.high` package.
```scala
valueStream
.through(data.cbor.high.toBinary)
.compile
.to(ByteVector)
.map(_.toHex)
```
--------------------------------
### Parse CBOR binary stream to low-level items
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/cbor/index.md
Use the `items` pipe to parse a CBOR binary stream into a low-level representation. Ensure necessary imports are included.
```scala
import fs2._
import fs2.data.cbor.low._
import scodec.bits._
val byteStream = Stream.chunk(Chunk.byteVector(hex"8301820203820405"))
val itemStream = byteStream.through(items[Fallible])
itemStream.compile.toList
```
--------------------------------
### Compile and Use a Query with FS2 Stream
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/jq.md
Compile a query once and reuse it with an FS2 stream for efficient data processing. Ensure the stream is processed through the compiled query.
```scala
val qCompiler = jq.Compiler[SyncIO]
val compiled = qCompiler.compile(query).unsafeRunSync()
stream
.through(compiled)
.compile
.to(collector.pretty())
.unsafeRunSync()
```
--------------------------------
### StaticHeaders Instance Definition
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/index.md
Define a `StaticHeaders` instance to provide headers for encoding and decoding when they are not present in the data itself. This is useful for pipes like `decodeUsingStaticHeaders` and `encodeUsingStaticHeaders`.
```scala
implicit val staticHeadersForMyRow: StaticHeaders[MyRow, String] = StaticHeaders.instance(NonEmptyList.of("i", "s", "j"))
```
--------------------------------
### Build XML DOM Document
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/index.md
Builds an XML DOM of a specified type from an XML event stream. Requires an implicit DocumentBuilder instance for the target DOM type.
```scala
import dom._
trait SomeDocType
implicit val builder: DocumentBuilder[SomeDocType] = ???
stream.through(documents[IO, SomeDocType])
```
--------------------------------
### Collect Raw XML String
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/index.md
Collects an XML event stream into a raw XML string.
```scala
stream.compile.to(collector.raw()).unsafeRunSync()
```
--------------------------------
### Compile jq query into a pipe
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jq.md
Compiles a defined jq query into an fs2 Pipe using the Compiler class. This prepares the query for use in an fs2 stream transformation.
```scala
import fs2.data.json.jq.Compiler
val queryCompiler = Compiler[IO]
val queryPipe = queryCompiler.compile(query).unsafeRunSync()
```
--------------------------------
### Deserialize MessagePack Bytes to a Stream of Custom Objects
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
Deserializes a stream of MessagePack bytes back into a stream of User objects using the defined MsgpackDeserializer. The result is collected into a list.
```scala
byteStream
.through(data.msgpack.high.deserialize[Fallible, User])
.compile.toList
```
--------------------------------
### Convert MessagePack Bytes to AST Values
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
Converts a stream of MessagePack bytes into a stream of MsgpackValue AST nodes. This allows for more flexible, albeit potentially less performant, handling of MessagePack data.
```scala
val valueStream = byteStream.through(data.msgpack.high.ast.valuesFromBytes)
```
--------------------------------
### Build AST Values from Token Stream
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/index.md
Use the `values` pipe to build JSON ASTs from an existing token stream. Requires an implicit `Builder[Json]` in scope. This method is less efficient than `ast.parse` if only values are required.
```scala
import ast._
trait SomeJsonType
implicit val builder: Builder[SomeJsonType] = ???
stream.through(values[Fallible, SomeJsonType])
```
--------------------------------
### Writing CSV
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/index.md
Provides pipes for encoding rows to CSV format, with or without headers.
```APIDOC
## Writing CSV
There are pipes for encoding rows to CSV, with or without headers.
### Writing without headers
```scala
val testRows = Stream(Row(NonEmptyList.of("3", "", "test")))
testRows
.through(lowlevel.writeWithoutHeaders)
.through(lowlevel.toRowStrings(/* separator: Char = ',', newline: String = "\n"*/))
.compile
.string
```
### Writing with headers
Use `writeWithGivenHeaders` or `encodeRowWithFirstHeaders` for `CsvRow`. For non-String headers, provide an instance of `WritableHeader`.
```scala
// Example for writing with headers (assuming 'stream' is defined and has headers)
// val withh = stream.through(lowlevel.headers[Fallible, String])
// withh.through(lowlevel.writeWithGivenHeaders).compile.string
```
```
--------------------------------
### Parse XML to Stream of Events
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/index.md
Creates a stream of XML events from an input string. This pipe validates XML structure during parsing.
```scala
import cats.effect._
import cats.effect.unsafe.implicits.global
import fs2._
import fs2.data.xml._
val input = """
| text
|
|
|
| test entity resolution & normalization
|""".stripMargin
val stream = Stream.emit(input).through(events[IO, String]())
```
--------------------------------
### Collect Raw XML Matches Non-Deterministically
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/xpath.md
Similar to collecting raw XML matches, but setting `deterministic = false` allows results to be emitted as early as possible, rather than in order.
```scala
stream
.lift[IO]
.through(filter.collect(path, collector.raw(), deterministic = false))
.compile
.toList
.unsafeRunSync()
```
--------------------------------
### Decode Textual Input with ISO-8859-1 Encoding
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/index.md
Shows how to decode a stream of bytes from a file into characters using the ISO-8859-1 (latin1) encoding. This is necessary for textual data formats when the file is not UTF-8 encoded. The `tokens` pipe is then applied to the decoded character stream.
```scala
// for instance if your input is encoded in ISO-8859-1 aka latin1
import fs2.data.text.latin1._
// if you have UTF-8 instead:
// import fs2.data.text.utf8._
Files[IO]
.readAll(Path("/some/path/to/a/file.data"), 1024, Flags.Read)
// decoding is done by the now in scope `CharLikeChunks[IO, Byte]` instance
.through(tokens)
.compile
.drain
```
--------------------------------
### Parse XPath String
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/xpath.md
Demonstrates parsing an XPath string into a selector using XPathParser.either. This method wraps the result in a MonadError to handle potential parsing errors.
```scala
import fs2.data.xml.xpath._
val selector = XPathParser.either("//a")
```
--------------------------------
### Parse JSON Stream to AST Values
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/index.md
Use the `ast.parse` pipe to directly parse an input stream into a stream of AST values. Requires an implicit `Builder[Json]` in scope. This is more efficient than tokenizing first if only values are needed.
```scala
import ast._
trait SomeJsonType
implicit val builder: Builder[SomeJsonType] = ???
Stream.emit(input).covary[Fallible].through(parse)
```
--------------------------------
### Resolve XML Namespaces
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/index.md
Applies namespace resolution to an existing stream of XML events. Requires an IO context.
```scala
val nsResolved = stream.through(namespaceResolver[IO])
```
--------------------------------
### Serialize MsgpackItem Stream to Non-Validated Binary
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
Use the `toNonValidatedBinary` pipe when you are certain the item stream is valid. This bypasses stream validation for potentially faster serialization.
```scala
inputStream.through(data.msgpack.low.toNonValidatedBinary)
```
--------------------------------
### Generate JSON Array Wrapped in Object
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/index.md
Wraps a stream of tokenized events into a JSON array under the key "events". Requires `fs2.data.json.circe._` for Circe integration and `fs2.data.json.ast.tokenize`.
```scala
import fs2.data.json.circe._
val wrappedTokens = events.through(ast.tokenize).through(wrap.asArrayInObject(at = "events"))
```
--------------------------------
### Define MsgpackDeserializer for a Custom Case Class
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
Defines an implicit MsgpackDeserializer for a custom User case class. This involves sequencing deserializers for each field and then constructing the User object.
```scala
implicit val userDeserializer: MsgpackDeserializer[User] =
for {
name <- MsgpackDeserializer[String]
age <- MsgpackDeserializer[Int]
created <- MsgpackDeserializer[Instant]
visits <- MsgpackDeserializer[List[Long]]
} yield User(name, age, created, visits)
```
--------------------------------
### Derive CellDecoder and CellEncoder for Unary Products and Aliases
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/generic.md
Shows how to derive CellDecoder and CellEncoder for unary product types (case classes with one field) and how to handle custom CSV value annotations for coproduct members. Requires an implicit CellDecoder[String] for the field.
```scala
import fs2.data.csv.generic.semiauto._
sealed trait Advanced
object Advanced {
@CsvValue("Active") case object On extends Advanced
case class Unknown(name: String) extends Advanced
}
// works as we have an implicit CellDecoder[String]
implicit val unknownDecoder = deriveCellDecoder[Advanced.Unknown]
implicit val advancedDecoder = deriveCellDecoder[Advanced]
advancedDecoder("Active")
advancedDecoder("Off")
implicit val unknownEncoder = deriveCellEncoder[Advanced.Unknown]
implicit val advancedEncoder = deriveCellEncoder[Advanced]
advancedEncoder(Advanced.On)
advancedEncoder(Advanced.Unknown("Off"))
```
--------------------------------
### Collect Pretty-Printed XML String
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/index.md
Collects an XML event stream into a pretty-printed XML string.
```scala
stream.compile.to(collector.pretty()).unsafeRunSync()
```
--------------------------------
### Define MsgpackSerializer for a Custom Case Class
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
Defines an implicit MsgpackSerializer for a custom User case class. This involves mapping each field of the case class to its corresponding MsgpackSerializer and concatenating the results.
```scala
import fs2.*
import fs2.data.msgpack.high.*
import java.time.Instant
case class User(name: String, age: Int, created: Instant, visits: List[Long])
implicit val userSerializer: MsgpackSerializer[User] = {
case User(name, age, created, visits) =>
for {
name <- MsgpackSerializer[String](name)
age <- MsgpackSerializer[Int](age)
created <- MsgpackSerializer[Instant](created)
visits <- MsgpackSerializer[List[Long]](visits)
} yield name ++ age ++ created ++ visits
}
```
--------------------------------
### Convert AST Values back to MessagePack Bytes
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
Converts a stream of MsgpackValue AST nodes back into a stream of MessagePack bytes. This is useful for re-serializing data that has been processed or manipulated as AST nodes.
```scala
val byteStream2 = valueStream.through(data.msgpack.high.ast.valuesToBytes)
```
--------------------------------
### Convert Values to JSON Tokens
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/index.md
Use the `tokenize` pipe to convert a stream of values into a stream of JSON tokens. Requires an implicit `Tokenizer[SomeJsonType]` in scope.
```scala
import ast._
trait SomeJsonType
val v: SomeJsonType = ???
implicit val tokenizer: Tokenizer[SomeJsonType] = ???
Stream.emit(v).through(tokenize[Fallible, SomeJsonType])
```
--------------------------------
### Migrate from circe-fs2 stringStreamParser to fs2-data-json
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/libraries.md
Replaces `circe-fs2`'s `stringStreamParser` with `fs2.data.json.ast.parse` for parsing JSON streams. The output is formatted with two spaces and collected into a list.
```scala
import io.circe.fs2._
import cats.effect._
input[SyncIO]
.through(stringStreamParser)
.map(_.spaces2)
.compile
.toList
.unsafeRunSync()
```
--------------------------------
### Read JSON file and write to stdout
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jq.md
Reads a JSON file using fs2-io and writes its content to standard output. This snippet uses pure fs2 operators and does not involve fs2-data.
```scala
import cats.effect.IO
import cats.effect.unsafe.implicits.global
import fs2.io.file.{Files, Path}
import fs2.io.stdout
import fs2.text.utf8
Files[IO]
.readUtf8(Path("site/cookbooks/data/json/sample.json"))
.through(utf8.encode[IO])
.through(stdout)
.compile
.drain
.unsafeRunSync()
```
--------------------------------
### Create RowEncoder for Case Class
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/index.md
Use `RowEncoder.forColumns` to create a `RowEncoder` for a simple positional case class, simplifying the encoding process. This method takes a function that extracts the fields from the case class.
```scala
case class Triple(i: Int, s: String, j: Int)
val tripleEncoder: RowEncoder[Triple] =
RowEncoder.forColumns((t: Triple) => (t.i, t.s, t.j))
```
--------------------------------
### Parse JSONPath Selector String
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/jsonpath.md
Creates a JSONPath selector by parsing a string. The result is wrapped in a MonadError to handle potential parsing errors. Import fs2.data.json.jsonpath._.
```scala
import fs2.data.json.jsonpath._
val selector = JsonPathParser.either("$.field3[*]")
```
--------------------------------
### CsvRowDecoder and CsvRowEncoder with forColumns Helper
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/index.md
Use the `forColumns` helper to reduce boilerplate when mapping named CSV columns to case class constructor arguments or tuple elements. This method simplifies the creation of decoders and encoders by accepting column names and a mapping function.
```scala
case class NamedRow(i: Int, j: Int, s: String)
val namedDecoder: CsvRowDecoder[NamedRow, String] =
// Depending on your Scala version, you might also be able to use .forColumns(NamedRow.apply) instead
CsvRowDecoder.forColumns("i", "j", "s")(NamedRow(_, _, _))
val namedEncoder: StaticCsvRowEncoder[NamedRow, String] =
CsvRowEncoder.forColumns("i", "j", "s")((r: NamedRow) => (r.i, r.j, r.s))
```
--------------------------------
### Parse and pretty-print JSON
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jq.md
Parses JSON input from a file and pretty-prints the resulting JSON stream to standard output using fs2-data-json pipes.
```scala
import fs2.data.json
Files[IO]
.readUtf8(Path("site/cookbooks/data/json/sample.json"))
.through(json.tokens) // parsing JSON input
.through(json.render.prettyPrint()) // pretty printing JSON stream
.through(utf8.encode[IO])
.through(stdout)
.compile
.drain
.unsafeRunSync()
```
--------------------------------
### Render Wrapped JSON Stream to List
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/index.md
Renders the wrapped JSON token stream (generated by `wrap.asArrayInObject`) into a list of strings. This is useful for inspecting the generated JSON.
```scala
wrappedTokens.through(render.compact).compile.toList
```
--------------------------------
### Transform and Serialize JSON Data with Circe
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/libraries.md
Transforms JSON data using a specified selector and a wrapping function, then serializes the result into a pretty-printed string. This demonstrates deserializing into `Data`, transforming it, and then serializing `WrappedData`.
```scala
import fs2.data.json.selector._
import fs2.data.json.circe._
val values = stream.through(codec.deserialize[Fallible, Data])
values.compile.toList
def wrap(data: Data): WrappedData =
WrappedData(data.field1, data.field2, data.field3.map(Wrapped(_)))
val sel = root.field("field3").iterate.compile
val transformed = stream.through(codec.transform(sel, wrap))
transformed.compile.to(collector.pretty())
```
--------------------------------
### Parse and Serialize CSV with Case Classes
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/index.md
Use this snippet for the common task of parsing CSV into a case class or serializing data into CSV. It assumes the CSV contains headers and uses them for encoding. Type class instances for `CsvRowDecoder` and `CsvRowEncoder` determine how data is decoded/encoded.
```scala
import cats.effect._
import fs2._
import fs2.data.csv._
import fs2.data.csv.generic.semiauto._
val input = """i,s,j
1,test,2
,other,-3
""".stripMargin
// Usually this would come from a file, for example using Files[IO].readAll
val textStream = Stream.emit(input).covary[Fallible]
implicit val myRowDecoder: CsvRowDecoder[MyRow, String] = deriveCsvRowDecoder
implicit val myRowEncoder: CsvRowEncoder[MyRow, String] = deriveCsvRowEncoder
// decodeUsingHeaders can take a `Char` indicating the separator to use
// for example `decodeUsingHeaders[MyRow](';') for a semi-colon separated csv
val decodedStream = textStream.through(decodeUsingHeaders[MyRow]())
val caseClasses = decodedStream.compile.toList
val backAsText = decodedStream.through(encodeUsingFirstHeaders(fullRows = true)).compile.string
```
--------------------------------
### Convert XML DOM to Events
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/xml/index.md
Transforms a stream of XML DOM documents back into a stream of XML events. Requires implicit DocumentBuilder and DocumentEventifier instances.
```scala
import dom._
trait SomeDocType
implicit val builder: DocumentBuilder[SomeDocType] = ???
implicit val eventifier: DocumentEventifier[SomeDocType] = ???
stream.through(documents[IO, SomeDocType])
.through(eventify[IO, SomeDocType])
```
--------------------------------
### Serialize Values to JSON Tokens
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/index.md
Use the `serialize` pipe to serialize a stream of values into a stream of JSON tokens. Requires an implicit `Serializer[T]` for the value type `T`.
```scala
import codec._
implicit val serializer: Serializer[String] = ???
Stream("a", "b", "c").through(serialize)
```
--------------------------------
### Decode CBOR Items with Tags to JSON Tokens
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/cbor-json/index.md
Demonstrates decoding CBOR items with specific tags (e.g., base64 encoding, positive big numbers) into JSON tokens. Supports tags for byte string interpretation.
```scala
import fs2.data.cbor.Tags
Stream
.emits(List(
CborItem.Tag(Tags.ExpectedBase64Encoding),
CborItem.StartArray(2),
CborItem.ByteString(hex"cafebabe"),
CborItem.ByteString(hex"ff"),
CborItem.Tag(Tags.PositiveBigNum),
CborItem.ByteString(hex"1234567890abcdef")
))
.through(cbor.json.decodeItems[Fallible])
.compile
.toList
```
--------------------------------
### Case Class Derivation with Default Values
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/generic.md
Supports default values in case classes for decoding. Missing columns or empty cell values are treated as defaults. Refrain from defining defaults or define manually if explicit empty value handling is needed.
```scala
import fs2.data.csv.generic.auto._
case class MyRowDefault(i: Int = 42, j: Int, s: String)
val decoded = stream.through(decodeUsingHeaders[MyRowDefault]())
```
--------------------------------
### Transform JSON data using a compiled jq pipe
Source: https://github.com/gnieh/fs2-data/blob/main/site/cookbooks/jq.md
Applies a compiled jq query pipe to transform JSON data read from a file. The transformed data is then pretty-printed and written to standard output.
```scala
Files[IO]
.readUtf8(Path("site/cookbooks/data/json/sample.json"))
.through(json.tokens)
.through(queryPipe) // the transformation using the query pipe
.through(json.render.prettyPrint())
.through(utf8.encode[IO])
.through(stdout)
.compile
.drain
.unsafeRunSync()
```
--------------------------------
### Define Data Models for Circe Deserialization
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/libraries.md
Defines case classes `Data`, `WrappedData`, and `Wrapped` with `@JsonCodec` annotations for use with Circe's generic derivation. These models represent the structure of the JSON data.
```scala
import io.circe.generic.JsonCodec
@JsonCodec
case class Data(field1: Int, field2: Option[String], field3: List[Int])
@JsonCodec
case class WrappedData(field1: Int, field2: Option[String], field3: List[Wrapped])
@JsonCodec
case class Wrapped(test: Int)
```
--------------------------------
### Manual CsvRowDecoder Implementation
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/index.md
Implement a CsvRowDecoder manually to decode CSV rows into a case class. This is useful when the CSV headers do not directly map to constructor arguments or when custom logic is needed for decoding fields. Ensure all required fields are handled.
```scala
case class MyRow(i: Option[Int], j: Int, s: String)
implicit object MyRowDecoder extends CsvRowDecoder[MyRow, String] {
def apply(row: CsvRow[String]): DecoderResult[MyRow] =
for {
i <- row.as[Int]("i").map(Some(_)).leftFlatMap(_ => Right(None))
j <- row.as[Int]("j")
s <- row.as[String]("s")
} yield MyRow(i, j, s)
}
val decoded = withh.through(lowlevel.decodeRow[Fallible, String, MyRow])
decoded.compile.toList
```
--------------------------------
### Implement Custom CellEncoder for Wrapper
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/index.md
Define a `CellEncoder` for a custom `Wrapper` case class. This can be done directly by providing a function from `Wrapper` to `String`, or by using `contramap` on an existing `CellEncoder` for `String`.
```scala
case class Wrapper(content: String)
implicit val wrapperCellEncoder: CellEncoder[Wrapper] = (w: Wrapper) => w.content
```
```scala
implicit val wrapperCellEncoder2: CellEncoder[Wrapper] = CellEncoder[String].contramap(_.content)
```
--------------------------------
### Derive CellDecoder and CellEncoder for Coproducts
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/csv/generic.md
Demonstrates how to automatically derive CellDecoder and CellEncoder instances for sealed traits (coproducts) using generic derivation. This allows decoding and encoding of custom enumerated types.
```scala
import fs2.data.csv.generic._
import fs2.data.csv.generic.semiauto._
sealed trait State
object State {
case object On extends State
case object Off extends State
}
implicit val stateDecoder = deriveCellDecoder[State]
// use stateDecoder to derive decoders for rows...or just test:
stateDecoder("On")
stateDecoder("Off")
// same goes for the encoder
implicit val stateEncoder = deriveCellEncoder[State]
stateEncoder(State.On)
```
--------------------------------
### Parse JSON Stream using fs2-data-json AST
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/libraries.md
Parses an input JSON stream into an AST using `fs2.data.json.ast.parse` and formats the output. This is the recommended replacement for `circe-fs2`'s `stringStreamParser`.
```scala
import fs2.data.json._
import fs2.data.json.circe._
input[Fallible]
.through(ast.parse)
.map(_.spaces2)
.compile
.toList
```
--------------------------------
### Validate MsgpackItem Stream
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
Apply the `validate` pipe directly to a stream of `MsgpackItem`s. This method will raise an error within the effect if the stream is malformed.
```scala
Stream(MsgpackItem.Array(999))
.through(data.msgpack.low.validate[Fallible])
.compile.toList
```
--------------------------------
### Validate MsgpackItem Stream
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/msgpack/index.md
The `validate` pipe can be applied directly to a stream of `MsgpackItem`s to validate its structure. It will raise an error within the effect if the stream is malformed.
```APIDOC
## validate
### Description
Validates a stream of `MsgpackItem`s. Raises an error within the effect if the stream is malformed.
### Method
Pipe
### Endpoint
N/A (Pipe)
### Parameters
N/A (Pipe)
### Request Example
```scala
Stream(MsgpackItem.Array(999))
.through(data.msgpack.low.validate[Fallible])
.compile.toList
```
### Response
#### Success Response
- `MsgpackItem`: The validated stream of MessagePack items.
#### Response Example
(Stream of MsgpackItems)
```
--------------------------------
### Parse JSON to Token Stream
Source: https://github.com/gnieh/fs2-data/blob/main/site/documentation/json/index.md
Use the `tokens` pipe to create a stream of JSON tokens from an input character stream. This pipe validates the JSON structure and emits tokens as they become available.
```scala
import cats.effect._
import cats.syntax.all._
import fs2._
import fs2.data.json._
val input = """
{
"field1": 0,
"field2": "test",
"field3": [1, 2, 3]
}
{
"field1": 2,
"field3": []
}
""".stripMargin
val stream = Stream.emit(input).through(tokens[Fallible, String])
stream.compile.toList
```