AvroJsoniter
Structural Avro ↔ JSON-'''bytes''' bridge: move between Avro generic runtime values / payload bytes and UTF-8 JSON byte arrays through jsoniter-scala's streaming JsonWriter / JsonReader, '''without''' a typed case class — and without a JSON AST — in the middle. The AST-free sibling of dev.constructive.eo.avro.circe.AvroJson: same walks, same conventions both ways, but the JSON side is Array[Byte] instead of io.circe.Json, so circe never touches the classpath. Lives inside cats-eo-avro with jsoniter-scala-core as an Optional dependency (the rendering runs through its JsonWriter) — add com.github.plokhotnyuk.jsoniter-scala:jsoniter-scala-core to use this package.
==Rendering conventions (record → JSON bytes)==
avroToJson mirrors AvroJson.avroToJson case for case, so the two bridges render parse-equivalent documents for the same record:
IndexedRecord→ object (field name fromgetSchema.getFields, recurse on value, schema declaration order);java.util.Map→ object (stringify keys, recurse on values, entry iteration order);java.util.List→ array (recurse);CharSequence(incl.org.apache.avro.util.Utf8) → JSON string;Integer/Long→ JSON number;Float/Double→ JSON number via jsoniter's shortest-round-trip rendering, non-finite values →null(matching circe'sfromFloatOrNull/fromDoubleOrNull);Boolean→ JSON boolean; a resolvednullunion branch →null;GenericEnumSymbol→ JSON string;ByteBuffer/GenericFixed→ array of signed byte ints (circe'sEncoder[Array[Byte]]convention, same asAvroJson);- any other runtime type → JSON string of
value.toString— a lenient last resort (the walk is total), not a convention to rely on.
Unions are resolved at the value level (the runtime value IS the branch), so dispatch on the runtime type needs no union special-casing.
==Codec diagonals==
The typed prism family mirrors AvroJson's, with JsoniterBytes in the Json slot: the fundamental diagonal valuePrism tears a generic runtime value into a typed A and mends any generic value out as JSON bytes; bytesPrism and recordPrism pre-compose its input slots via tearFrom / mendFrom. The AvroBytes / JsoniterBytes aliases (see the package object) keep the two Array[Byte] roles apart in the signatures.
==Drilled cursors (.json and .avro faces)==
The full AvroPrism cursor sugar — .field(_.x) / .fields(...) / .at(i) / .union[B] / .each / Dynamic selection — reaches this bridge through the json extensions on AvroPrism / AvroTraversal (drill first, flip last, like .record): reads yield the typed focus, writes render the whole modified document as JSON bytes. render is the focus-as-standalone-JSON terminal for the read side.
The reverse cursor is the avro extension on JsoniterPrism: drill a JSON document with the jsoniter sugar and the '''drilled focus itself''' converts — reads structurally parse the focused slice under the focus codec's schema and yield its Avro binary encoding, writes accept Avro binary, render it structurally, and splice the JSON slice back. Both directions are schema-directed walks; no typed value is ever materialised.
==Parsing conventions (JSON bytes → record)==
record's getOption (and the .avro face's read) is the '''strict''' schema-directed inverse — a streaming JsonReader walk, no AST — mirroring AvroJson's parsing conventions: a record object's key set must equal the schema's field names exactly; enum requires a schema symbol; fixed the exact byte length; bytes / fixed the signed-byte-int array rendering; a union is matched '''first branch that parses wins''' (the branch slice is captured raw once and re-attempted per branch — a streaming reader cannot backtrack). Two deliberate strictness-only divergences from the AST parse: numeric syntax is token-level (1.0 misses an int schema where circe's toInt accepts it), and a duplicate object key misses (circe's JsonObject silently de-duplicates before AvroJson ever sees it).
==Non-goals (deliberate)==
Same as AvroJson: the bridge sees only the '''runtime''' Avro value, never the logical type — an Instant stored as timestamp-millis renders as a JSON number, not an ISO-8601 string.
Attributes
- Source
- AvroJsoniter.scala
- Graph
-
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
AvroJsoniter.type