{"id":13652938,"url":"https://github.com/plokhotnyuk/jsoniter-scala","last_synced_at":"2026-01-02T14:11:24.285Z","repository":{"id":37839289,"uuid":"104897792","full_name":"plokhotnyuk/jsoniter-scala","owner":"plokhotnyuk","description":"Scala macros for compile-time generation of safe and ultra-fast JSON codecs + circe booster","archived":false,"fork":false,"pushed_at":"2025-04-25T10:31:01.000Z","size":7115282,"stargazers_count":771,"open_issues_count":88,"forks_count":104,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-04-27T04:53:11.736Z","etag":null,"topics":["circe","high-performance","jmh-benchmarks","json","jsoniter-scala","jvm","library","macros","parsing","scala","scala-js","scala-library","scala-native","scala3","scalajs","serialization"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/plokhotnyuk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"plokhotnyuk","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2017-09-26T14:47:09.000Z","updated_at":"2025-04-26T13:28:22.000Z","dependencies_parsed_at":"2024-05-20T09:25:42.070Z","dependency_job_id":"e0654422-5229-4e37-bcff-834557f63b7b","html_url":"https://github.com/plokhotnyuk/jsoniter-scala","commit_stats":null,"previous_names":[],"tags_count":380,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plokhotnyuk%2Fjsoniter-scala","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plokhotnyuk%2Fjsoniter-scala/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plokhotnyuk%2Fjsoniter-scala/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plokhotnyuk%2Fjsoniter-scala/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/plokhotnyuk","download_url":"https://codeload.github.com/plokhotnyuk/jsoniter-scala/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251089604,"owners_count":21534517,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["circe","high-performance","jmh-benchmarks","json","jsoniter-scala","jvm","library","macros","parsing","scala","scala-js","scala-library","scala-native","scala3","scalajs","serialization"],"created_at":"2024-08-02T02:01:04.162Z","updated_at":"2025-12-28T13:40:43.554Z","avatar_url":"https://github.com/plokhotnyuk.png","language":"Scala","funding_links":["https://github.com/sponsors/plokhotnyuk"],"categories":["Libraries","Table of Contents","JSON"],"sub_categories":["JSON"],"readme":"# jsoniter-scala\n\n[![Actions Build](https://github.com/plokhotnyuk/jsoniter-scala/workflows/build/badge.svg)](https://github.com/plokhotnyuk/jsoniter-scala/actions)\n[![Scala Steward](https://img.shields.io/badge/Scala_Steward-helping-brightgreen.svg?style=flat\u0026logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAMAAAARSr4IAAAAVFBMVEUAAACHjojlOy5NWlrKzcYRKjGFjIbp293YycuLa3pYY2LSqql4f3pCUFTgSjNodYRmcXUsPD/NTTbjRS+2jomhgnzNc223cGvZS0HaSD0XLjbaSjElhIr+AAAAAXRSTlMAQObYZgAAAHlJREFUCNdNyosOwyAIhWHAQS1Vt7a77/3fcxxdmv0xwmckutAR1nkm4ggbyEcg/wWmlGLDAA3oL50xi6fk5ffZ3E2E3QfZDCcCN2YtbEWZt+Drc6u6rlqv7Uk0LdKqqr5rk2UCRXOk0vmQKGfc94nOJyQjouF9H/wCc9gECEYfONoAAAAASUVORK5CYII=)](https://scala-steward.org)\n[![Gitter Chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/plokhotnyuk/jsoniter-scala?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![Maven Central](https://img.shields.io/badge/maven--central-2.38.7-blue.svg)](https://repo1.maven.org/maven2/com/github/plokhotnyuk/jsoniter-scala/)\n\nScala macros for compile-time generation of safe and ultra-fast JSON codecs.\n\n[**Latest results of benchmarks on JVMs**](https://plokhotnyuk.github.io/jsoniter-scala/) that compare parsing and\nserialization performance of jsoniter-scala with: [borer](https://github.com/sirthias/borer), \n[circe](https://github.com/circe/circe), \n[circe with jsoniter-scala booster](https://github.com/plokhotnyuk/jsoniter-scala/tree/master/jsoniter-scala-circe),\n[jackson-module-scala](https://github.com/FasterXML/jackson-module-scala),\n[json4s-jackson](https://github.com/json4s/json4s/tree/master/jackson),\n[json4s-native](https://github.com/json4s/json4s/tree/master/native),\n[play-json](https://github.com/playframework/play-json),\n[play-json with jsoniter-scala booster](https://github.com/evolution-gaming/play-json-tools/tree/master/play-json-jsoniter),\n[smithy4s-json](https://github.com/disneystreaming/smithy4s/tree/main/modules/json),\n[spray-json](https://github.com/spray/spray-json), [uPickle](https://github.com/lihaoyi/upickle),\n[weePickle](https://github.com/rallyhealth/weePickle), [zio-blocks](https://github.com/zio/zio-blocks), \n[zio-json](https://github.com/zio/zio-json), [zio-schema-json](https://github.com/zio/zio-schema/tree/main/zio-schema-json)\nlibraries using different JDK and GraalVM versions on the following environment: Intel® Core™ Ultra 9 285K CPU @ 3.7GHz\n(max 5.7GHz, 200S Boost), RAM 64Gb DDR5-6400, Ubuntu Server 25.04 (Linux 6.14), and latest versions of JDK 17/21/25,\nGraalVM Community JDK 17/21/25, and GraalVM JDK 17/21/25[*](https://docs.google.com/spreadsheets/d/1IxIvLoLlLb0bxUaRgSsaaRuXV0RUQ3I04vFqhDc2Bt8/edit?usp=sharing).\n\n[**Latest results of benchmarks on browsers**](https://plokhotnyuk.github.io/jsoniter-scala/index-scalajs.html) that\ncompare performance of jsoniter-scala with: [circe](https://github.com/circe/circe), \n[circe with jsoniter-scala booster](https://github.com/plokhotnyuk/jsoniter-scala/tree/master/jsoniter-scala-circe),\n[play-json](https://github.com/playframework/play-json),\n[play-json with jsoniter-scala booster](https://github.com/evolution-gaming/play-json-tools/tree/master/play-json-jsoniter),\n[smithy4s-json](https://github.com/disneystreaming/smithy4s/tree/main/modules/json),\n[uPickle](https://github.com/lihaoyi/upickle), [zio-blocks](https://github.com/zio/zio-blocks), \n[zio-json](https://github.com/zio/zio-json), and [zio-schema-json](https://github.com/zio/zio-schema/tree/main/zio-schema-json)\ncompiled by Scala.js 1.20.1 to ES 2021 with GCC v20220202 optimizations applied on\nIntel® Core™ Ultra 9 285K CPU @ 3.7GHz (max 5.7GHz, 200S Boost), RAM 64Gb DDR5-6400, Ubuntu Desktop 25.04 (Linux 6.14) and \nlatest versions of web browsers.\n\n## Contents\n\n- [Acknowledgments](#acknowledgments)\n- [Goals](#goals)\n- [Features and limitations](#features-and-limitations)\n- [**How to use**](#how-to-use)\n- [Known issues](#known-issues)\n- [How to develop](#how-to-develop)\n\n## Acknowledgments\n\nThis library had started from macros that reused [jsoniter (json-iterator) for Java](https://github.com/json-iterator/java) \nreader and writer but then the library evolved to have its own core of mechanics for parsing and serialization.\n\nThe idea to generate codecs by Scala macros and main details were borrowed from\n[Kryo Macros](https://github.com/evolution-gaming/kryo-macros) (originally developed by [Alexander Nemish](https://github.com/nau)) and adapted for the needs of the JSON domain.\n  \nOther Scala macros features were peeped in [AVSystem Commons](https://github.com/AVSystem/scala-commons/tree/master/commons-macros/src/main/scala/com/avsystem/commons/macros)\nand [magnolia](https://github.com/softwaremill/magnolia) libraries.\n\nIdeas for the most efficient parsing and serialization of `java.time.*` values were inspired by\n[DSL-JSON](https://github.com/ngs-doo/dsl-json)'s implementation for `java.time.OffsetDateTime`.\n\nOther projects and a blog post that have helped deliver unparalleled safety and performance characteristics for parsing\nand serialization of numbers:\n- [Schubfach](https://github.com/c4f7fcce9cb06515/Schubfach/) - the most efficient and concise way to serialize doubles \n  and floats to the textual representation\n- [rust-lexical](https://github.com/Alexhuszagh/rust-lexical) - the most efficient way to parse floats and doubles from\n  the textual representation precisely\n- [big-math](https://github.com/eobermuhlner/big-math) - parsing of `BigInt` and `BigDecimal` values with the `O(n^1.5)`\n  complexity instead of `O(n^2)` using Java's implementations where `n` is a number of digits\n- [James Anhalt's algorithm](https://jk-jeon.github.io/posts/2022/02/jeaiii-algorithm/) - the ingenious algorithm for \n  printing integers into decimal strings\n  \nA bunch of SWAR technique tricks for JVM platform are based on following projects and a blog post:\n- [borer](https://github.com/sirthias/borer/blob/fde9d1ce674d151b0fee1dd0c2565020c3f6633a/core/src/main/scala/io/bullet/borer/json/JsonParser.scala#L456) - the fast parsing of JSON strings by 8-byte words\n- [simdjson](https://github.com/simdjson/simdjson/blob/7e1893db428936e13457ba0e9a5aac0cdfb7bc15/include/simdjson/generic/numberparsing.h#L344) - the fast checking of string for digits by 8-byte words\n- [FastDoubleParser](https://github.com/wrandelshofer/FastDoubleParser/blob/0903817a765b25e654f02a5a9d4f1476c98a80c9/src/main/java/ch.randelshofer.fastdoubleparser/ch/randelshofer/fastdoubleparser/FastDoubleSimd.java#L114-L130) - the fast parsing of numbers by 8-byte words\n- [Johnny Lee's article](https://johnnylee-sde.github.io/Fast-time-string-to-seconds/) - the fast time string to seconds\n  conversion\n\nBig kudos to all contributors:\n\n[![GitHub contributors](https://contrib.rocks/image?repo=plokhotnyuk/jsoniter-scala)](https://github.com/plokhotnyuk/jsoniter-scala/graphs/contributors)\n\n\n## Goals\n\n1. **Safety**: validate parsed values safely with the fail-fast approach and clear reporting, provide configurable \nlimits for suboptimal data structures with safe defaults to be resilient for DoS attacks, generate codecs that create\ninstances of a _fixed_ set of classes during parsing to avoid RCE attacks\n2. **Correctness**: support the latest JSON format (RFC-8259), do not replace illegally encoded characters of string \nvalues by placeholder characters, parse numbers with limited binary representation doing half even rounding for too \nlong JSON numbers, serialize floats and doubles to the _shortest_ textual representation without loosing of precision \n3. **Speed**: do parsing and serialization of JSON directly from UTF-8 bytes to your data structures and back, do it \ncrazily fast without using of runtime reflection or runtime code generation, intermediate ASTs, hash maps, but with \nminimum allocations and copying\n4. **Productivity**: derive codecs recursively for complex types using one line macro, do it in _compile-time_ to \nminimize the probability of run-time issues, optionally print generated sources as compiler output to be inspected for \nproving safety and correctness or to be reused as a starting point for the implementation of custom codecs, prohibit \nserializing of `null` Scala values and parsing immediately to them in generated codecs\n5. **Ergonomics**: have preconfigured defaults for the safest and common usage that can be easily altered by compile- \nand run-time configuration instances, combined with compile-time annotations and implicits, embrace the textual \nrepresentation of JSON providing a pretty printing option, provide a hex dump in the error message to speed up the\nview of an error context\n\n## Features and limitations\n\n- JSON parsing from `String`, `Array[Byte]`, `java.nio.ByteBuffer`, `java.io.InputStream`/`java.io.FileInputStream`\n- JSON serialization to `String`, `Array[Byte]`, `java.nio.ByteBuffer`, `java.io.OutputStream`/`java.io.FileOutputStream`\n- Support of parsing from or writing to part of `Array[Byte]` or `java.nio.ByteBuffer` by specifying of position and \n  limit\n- Parsing of streaming JSON values and JSON arrays from `java.io.InputStream`/`java.io.FileInputStream` without the need\n  of holding all input and parsed values in the memory\n- Only UTF-8 encoding is supported when working with buffered bytes directly but there is a fallback to parse and\n  serialize JSON from/to `String` (while this is much less efficient)\n- Parsing of strings with escaped characters for JSON keys and string values\n- Codecs can be generated for primitives, boxed primitives, enums, tuples, `String`, `BigInt`, `BigDecimal`, `Option`,\n  `Either`, `java.util.UUID`, `java.time.*` (to/from ISO-8601 representation only), Scala collections, arrays\n  (including immutable arrays in Scala 3), module classes, literal types, value classes, and case classes with\n  values/fields having any of types listed here\n- Classes should be defined with a primary constructor that hasn't defined default values in non-first parameter lists\n- Non-case Scala classes also supported, but they should have getter accessors for all arguments of a primary\n  constructor\n- Types that supported as map keys are primitives, boxed primitives, enums, `String`, `BigInt`, `BigDecimal`,\n  `java.util.UUID`, `java.time.*`, literal types, and value classes for any of them\n- Codecs for sorted maps and sets can be customized by implicit `Ordering[K]` instances for keys that are available at\n  the scope of the `make` macro call\n- Core module support reading and writing byte arrays from/to Base16 and Base64 representations (RFC 4648) for using in \n  custom codecs    \n- Parsing of escaped characters is not supported for strings which are mapped to byte arrays, numeric and `java.time.*` \n  types\n- Support of first-order and higher-kind types\n- Support of 2 representations of ADTs with a sealed trait or a Scala class as a base type and non-abstract Scala \n  classes or objects as leaf classes: 1st representation uses discriminator field with string type of value, 2nd one \n  uses string values for objects and a wrapper JSON object with a discriminator key for case class instances\n- Implicitly resolvable value codecs for JSON values and key codecs for JSON object keys that are mapped to maps allows\n  to inject your custom codecs for adding support of other types or for altering representation in JSON for already\n  supported classes\n- Type aliases are supported for all types mentioned above\n- Only acyclic graphs of class instances are supported by generated codecs\n- Order of instance fields is preserved during serialization for generated codecs\n- Throws a parsing exception if duplicated keys were detected for a class instance (except maps)\n- Serialization of `null` values is prohibited by throwing of `NullPointerException` errors\n- Parsing of `null` values allowed only for optional or collection types (that means the `None` value or an empty \n  collection accordingly) and for fields which have defined non-null default values\n- Fields with default values that defined in the constructor are optional, other fields are required (no special\n  annotation required)\n- Fields with values that are equals to default values, or are empty options/collections/arrays are not serialized to\n  provide a sparse output\n- Any values that used directly or as part of default values of the constructor parameters should have right\n  implementations of the `equals` method (it mostly concerns non-case classes or other types that have custom codecs)\n- Fields can be annotated as transient or just not defined in the constructor to avoid parsing and serializing at all\n- Field names can be overridden for serialization/parsing by field annotation in the primary constructor of classes\n- Reading and writing of any arbitrary bytes or raw values are possible by using custom codecs\n- Parsing exception always reports a hexadecimal offset of `Array[Byte]`, `java.nio.ByteBuffer`, `java.io.InputStream`/\n  `java.io.FileInputStream` where it occurs, and an optional hex dump affected by error part of an internal byte buffer\n- Configurable by field annotation ability to read/write numeric fields from/to string values\n- Both key and value codecs are specialized to work with primitives efficiently without boxing/unboxing\n- No extra buffering is required when parsing from `java.io.InputStream`/`java.io.FileInputStream` or serializing to\n  `java.io.OutputStream`/`java.io.FileOuputStream`\n- Using black box macros only for codec generation ensures that your types will never be changed\n- Generated code is ordered to preserve checksums and maximize hit rate for remote caches of build tools\n- Ability to print generated code for codecs using an implicit val of `CodecMakerConfig.PrintCodec` type in a scope of \n  codec derivation\n- No dependencies on extra libraries in _runtime_ excluding Scala's `scala-library` (all platforms) and\n  `scala-java-time` (replacement of JDKs `java.time._` types for Scala.js and Scala Native)\n- On Scala.js and Scala Native platforms, if you need support for timezones besides `UTC` then you should follow the \n  [scala-java-time documentation](https://cquiroz.github.io/scala-java-time/#time-zones) for adding a time zone database\n  to your application\n- Codecs and runtime configurations implement `java.io.Serializable` for easier usage in distributive computing\n- Support of simple opaque types like `opaque type Foo = Int` and `opaque type Bar \u003c: String = String`\n- Support of tuples with arities greater than 22 for Scala 3 backed by `scala.runtime.TupleXXL`\n- Support of named tuples from Scala 3.7 while staying on Scala 3.3 (LTS)\n- Support of shading to another package for locking on a particular released version\n- Patch versions are backward and forward compatible, minor versions are backward compatible\n- Integration with circe for faster parsing/serialization and decoding/encoding to/from circe AST \n- Releases for different Scala versions: 2.12, 2.13, and 3.3\n- Support of JVMs for Java 11+ versions\n- Support of compilation to a native image by GraalVM\n- Support of Scala.js 1.0+ for all supported Scala versions\n- Support of Scala Native 0.5+ for all supported Scala versions\n- Suppressing of all WartRemover warnings of generated codecs for Scala 2.12 and 2.13 \n\nThere are configurable options that can be set in compile-time:\n- Ability to read/write numbers from/to string values\n- Ability to read/write maps as JSON arrays\n- Skipping of unexpected fields or throwing of parse exceptions\n- Skipping of serialization of fields that have empty collection values can be turned off to force serialization of them\n- Skipping of serialization of fields that have empty optional values can be turned off to force serialization of them\n- Skipping of serialization of fields which values are matched with defaults that are defined in the primary constructor\n  can be turned off to force serialization of that values\n- Ability to require collection fields in the JSON input\n- Ability to require fields with default values in the JSON input\n- Ability to override names of classes of ADTs and fields using a compile-time annotation  \n- Mapping functions from names of classes and their fields to JSON keys or from names of Java enumeration values to \n  JSON strings and back, including predefined functions which enforce snake_case, kebab-case, camelCase or \n  PascalCase names for all fields in the generated codec\n- An optional name of the discriminator field for ADTs\n- Mapping function for values of a discriminator field that is used for distinguishing classes of ADTs\n- Ability to set a precision, a scale limit, and the max number of significant digits when parsing `BigDecimal` values\n- Ability to set the max number of significant digits when parsing `BigInt` values\n- Ability to set the max allowed value when parsing bit sets\n- Ability to set the limit for the number of inserts when parsing sets or maps\n- Throwing of a compilation error for recursive data structures can be turned off\n- Throwing of a runtime error when the discriminator is not the first field can be turned off\n- Ability to parse/serialize Scala enumeration from/to id numbers\n- Ability to derive codecs that can distinguish `null` field values and missing fields as `Some(None)` and `None` values\n  of `Option[Option[_]]`\n- Ability to turn on circe-like encoding of Scala objects in ADTs\n- Ability to disable generation of implementation for decoding or encoding for faster derivation and less class/js/binary size\n- Ability to require fields that have defined default values\n- Ability to generate smaller and more efficient codecs for classes when checking of field duplication is not needed\n- Ability to inline non value classes which have the primary constructor with just one argument\n- Ability toggle serialization of fields with `null` values when using use custom codecs for Scala 3 union types with `Null` values \n\nList of options that change parsing and serialization in runtime:\n- Serialization of strings with escaped Unicode characters to be ASCII compatible\n- Indenting of output and its step\n- Throwing of stack-less parsing exceptions by default to greatly reduce the impact on performance, while stack traces\n  can be turned on in development for debugging\n- Turning off hex dumping affected by error part of an internal byte buffer to reduce the impact on performance\n- Size of the hex dump can be adjusted for bigger or smaller number of 16-byte lines\n- Max size of internal input buffers when parsing from `java.io.InputStream` or `java.nio.DirectByteBuffer`\n- Preferred size of internal input buffers when parsing from `java.io.InputStream` or `java.nio.DirectByteBuffer`\n- Preferred size of internal output buffers when serializing to `java.io.OutputStream` or `java.nio.DirectByteBuffer`\n- Max size of char buffers when parsing string values\n- Preferred size of char buffers when parsing string values\n\nThe [**v2.13.5.2**](https://github.com/plokhotnyuk/jsoniter-scala/releases/tag/v2.13.5.2) release is the last version that\nsupports JDK 8+ and native image compilation with earlier versions of GraalVM.\n\nThe [**v2.13.3.2**](https://github.com/plokhotnyuk/jsoniter-scala/releases/tag/v2.13.3.2) release is the last version that\nsupports Scala 2.11.\n\nThe [**v2.30.2**](https://github.com/plokhotnyuk/jsoniter-scala/releases/tag/v2.30.2) release is the last version that\nsupports Scala Native 0.4+.\n\n\nFor upcoming features and fixes see [Commits](https://github.com/plokhotnyuk/jsoniter-scala/commits/master)\nand [Issues page](https://github.com/plokhotnyuk/jsoniter-scala/issues).\n\n## How to use\n\nLet's assume that you have the following data structures:\n```scala\ncase class Device(id: Int, model: String)\n\ncase class User(name: String, devices: Seq[Device])\n```\n\nAdd the core library with a \"compile\" scope and the macros library with \"compile-internal\" or \"provided\" scopes to your \nlist of sbt dependencies:\n```sbt\nlibraryDependencies ++= Seq(\n  // Use the %%% operator instead of %% for Scala.js and Scala Native \n  \"com.github.plokhotnyuk.jsoniter-scala\" %% \"jsoniter-scala-core\" % \"2.38.7\",\n  // Use the \"provided\" scope instead when the \"compile-internal\" scope is not supported  \n  \"com.github.plokhotnyuk.jsoniter-scala\" %% \"jsoniter-scala-macros\" % \"2.38.7\" % \"compile-internal\"\n)\n```\nIn the beginning of Scala CLI script use \"dep\" scope for the core library or \"compileOnly.dep\" scope for the macros\nlibary:\n```scala\n//\u003e using dep \"com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-core::2.38.7\"\n//\u003e using compileOnly.dep \"com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-macros::2.38.7\"\n```\n\nDerive a codec for the top-level type that need to be parsed or serialized:\n```scala\nimport com.github.plokhotnyuk.jsoniter_scala.macros._\nimport com.github.plokhotnyuk.jsoniter_scala.core._\n\ngiven userCodec: JsonValueCodec[User] = JsonCodecMaker.make\n```\n\nThat's it! You have generated an instance of `com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec` for the\nwhole nested data structure. No need to derive intermediate codecs for inner nested classes like `Device` if you are not\ngoing to parse/serialize them from/to JSON in isolation (not as a part of `User`) and use the default or the same \nderivation configuration for their codecs.\n\nNow use it for parsing and serialization from/to `String`:\n```scala\nval user = readFromString[User](\"\"\"{\"name\":\"John\",\"devices\":[{\"id\":1,\"model\":\"HTC One X\"}]}\"\"\")\nval json = writeToString(User(\"John\", Seq(Device(2, \"iPhone X\"))))\n```\n\nWhen your input comes from the network or disks much more efficient ways are to parse and serialize from/to:\n- byte arrays using `readFromArray`/`writeToArray`\n- byte sub-arrays using `readFromSubArray`/`writeToSubArray`\n- `java.nio.ByteBuffer` instances using `readFromByteBuffer`/`writeToByteBuffer`\n- `java.io.InputStream`/`java.io.OutputStream` instances using `readFromStream`/`writeToStream`\n\nAlso, parsing from bytes will check `UTF-8` encoding and throw an error in case of malformed bytes.\n\nTo print generated code for codecs add the following line to the scope of the codec derivation before `make` call.\n\n```scala\ngiven CodecMakerConfig.PrintCodec with {}\n```\n\nFor more use cases of jsoniter-scala, please, check out tests:\n- [JsonCodecMakerSpec](https://github.com/plokhotnyuk/jsoniter-scala/blob/master/jsoniter-scala-macros/shared/src/test/scala/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodecMakerSpec.scala)\n- [PackageSpec](https://github.com/plokhotnyuk/jsoniter-scala/blob/master/jsoniter-scala-core/shared/src/test/scala/com/github/plokhotnyuk/jsoniter_scala/core/PackageSpec.scala)\n- [JsonReaderSpec](https://github.com/plokhotnyuk/jsoniter-scala/blob/master/jsoniter-scala-core/shared/src/test/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonReaderSpec.scala)\n- [JsonWriterSpec](https://github.com/plokhotnyuk/jsoniter-scala/blob/master/jsoniter-scala-core/shared/src/test/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonWriterSpec.scala)\n\nAll Scala 3 only features are tested by specs in [this directory](https://github.com/plokhotnyuk/jsoniter-scala/tree/master/jsoniter-scala-macros/shared/src/test/scala-3/com/github/plokhotnyuk/jsoniter_scala/macros).\n\n```text\nNOTE: Until official docs will be published, please, use all these tests as tutorials and how-tos to help in your \njourney to become happy users. Also, they are recommended to skim through for checking of your expectation before\nselection of this library among others.\n```\n\nYou can use the following on-line services to generate an initial version of your data structures from JSON\nsamples:\n- [json2caseclass](https://json2caseclass.cleverapps.io/)\n- [json-to-scala-case-class](https://transform.now.sh/json-to-scala-case-class/)\n- [json2classes](https://chadselph.github.io/json2classes/)\n- [quicktype](https://app.quicktype.io/)\n\nAlso, if you have JSON Schema the following on-line service can generate corresponding data structures for you:\n- [json-schema-to-case-class](https://cchandurkar.github.io/json-schema-to-case-class/)\n- [quicktype](https://app.quicktype.io/)\n\nAnd the following library can generate JSON Schema for your existing data structures:\n- [scala-jsonschema](https://github.com/andyglow/scala-jsonschema)\n\nSamples for its integration with different web frameworks and HTTP servers:\n- [akka-http](https://github.com/hseeberger/akka-http-json/blob/master/akka-http-jsoniter-scala/src/test/scala/de/heikoseeberger/akkahttpjsoniterscala/ExampleApp.scala)\n- [blaze](https://github.com/TechEmpower/FrameworkBenchmarks/blob/b3a39dcd95b207cd2509d7bbf873a0dfb91097f5/frameworks/Scala/blaze/src/main/scala/Main.scala)\n- [colossus](https://github.com/TechEmpower/FrameworkBenchmarks/blob/b3a39dcd95b207cd2509d7bbf873a0dfb91097f5/frameworks/Scala/colossus/src/main/scala/example/Main.scala)\n- [http4s](https://github.com/TechEmpower/FrameworkBenchmarks/blob/d1f960b2d4d6ea7b5c30a3ef2a8b47670f346f1c/frameworks/Scala/http4s/src/main/scala/WebServer.scala)\n- [pekko-http](https://github.com/pjfanning/pekko-http-json/blob/d8ca725bb5621e46c6df0c739ef83eb9f96bb3f1/pekko-http-jsoniter-scala/src/test/scala/com/github/pjfanning/pekkohttpjsoniterscala/ExampleApp.scala)\n- [Play (with Netty native transport)](https://github.com/plokhotnyuk/play/tree/master/src/main/scala/microservice)\n- [youi](https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Scala/youi/src/main/scala/example/Main.scala)\n- [zio-http](https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Scala/zio-http/src/main/scala/Main.scala)\n\nUsages of jsoniter-scala in OSS libraries:\n- [akka-http-json](https://github.com/hseeberger/akka-http-json) - integrates some of the best JSON libs in Scala with Akka HTTP \n- [bootzooka](https://github.com/softwaremill/bootzooka) - a project to quickly start developing a Scala-based microservice or web app,\n  without the need to write login, user registration etc.\n- [caliban](https://github.com/ghostdogpr/caliban) - a purely functional library for building GraphQL servers and \n  clients in Scala\n- [dijon](https://github.com/jvican/dijon) - support of schema-less JSON using safe and efficient AST representation\n- [geo-scala](https://github.com/gnieh/geo-scala) - a core AST and utilities for GeoJSON (RFC 7946) and more\n- [iron](https://github.com/Iltotore/iron) - a lightweight library for refined types in Scala 3\n- [jsoniter-scala-circe](https://github.com/plokhotnyuk/jsoniter-scala/tree/master/jsoniter-scala-circe) - the circe \n  booster for faster parsing/serialization to/form circe AST and decoding/encoding of `java.time._` and `BigInt` types\n- [kafka-serde-scala](https://github.com/azhur/kafka-serde-scala) - implicitly converts typeclass encoders to kafka Serializer, Deserializer, Serde\n- [logging4s](https://github.com/logging4s/logging4s) - structured logging for Scala 3\n- [neotype](https://github.com/kitlangton/neotype) - a friendly newtype library for Scala 3\n- [openapi-generator](https://github.com/OpenAPITools/openapi-generator) - a generator for Scala3 + sttp4 + jsoniter-scala\n- [oath](https://github.com/scala-jwt/oath) - yet another scala-jwt library which has the aim to enhance user experience\n- [pekko-http-json](https://github.com/pjfanning/pekko-http-json) - integrates some of the best JSON libs in Scala with Pekko HTTP \n- [play-json-jsoniter](https://github.com/evolution-gaming/play-json-tools) - provides the fastest way to convert an \n  instance of `play.api.libs.json.JsValue` to byte array (or byte buffer, or output stream) and read it back\n- [scalatest-json](https://github.com/stephennancekivell/scalatest-json) - Scalatest matchers with appropriate equality \n  and descriptive error messages\n- [smithy4s-json](https://github.com/disneystreaming/smithy4s) - JSON protocol of [Smithy](https://awslabs.github.io/smithy/)\n  tooling for Scala\n- [sttp](https://github.com/softwaremill/sttp) - the Scala HTTP client you always wanted! \n- [sttp-oauth2](https://github.com/polyvariant/sttp-oauth2) - OAuth2 client library implemented in Scala using sttp \n- [tapir](https://tapir.softwaremill.com/en/latest/endpoint/json.html#jsoniter-scala) - Typed API descRiptions\n\nAlso, for usages in other OSS projects see the `Dependents` section of [peoject's Scala Index page](https://index.scala-lang.org/plokhotnyuk/jsoniter-scala)\n\nFor all dependent projects it is recommended to use [sbt-updates plugin](https://github.com/rtimush/sbt-updates) or\n[Scala steward service](https://github.com/scala-steward) to keep up with using of the latest releases.\n\n## Known issues\n\n1. There is no validation for the length of JSON representation during parsing.\n\nIf your system can accept too long untrusted input then check the input length before parsing with `readFromStream`\nor other `read...` calls.\n\nAlso, if you have an input that is an array of values or white-space separate values then consider parsing it by\n`scanJsonArrayFromInputStream` or `scanJsonValuesFromInputStream` instead of `readFromStream`.\n\n2. The configuration parameter for the `make` macro is evaluated in compile-time. It requires no dependency\non other code that uses a result of the macro's call, otherwise the following compilation error will be reported:\n```\n[error] Cannot evaluate a parameter of the 'make' macro call for type 'full.name.of.YourType'. It should not depend on\n        code from the same compilation module where the 'make' macro is called. Use a separated submodule of the project\n        to compile all such dependencies before their usage for generation of codecs.\n```\nSometime Scala 2 compiler can fail to compile the `make` macro call with the same error message for the configuration \nthat has not clear dependencies on other code. For those cases workarounds can be simpler than recommended usage of\nseparated submodule:\n- use `make` or `make...` macro calls without parameters \n- isolate the `make` macro call in the separated object, like in [this PR](https://github.com/plokhotnyuk/play/pull/5/files)\n- move jsoniter-scala imports to be local, like [here](https://github.com/plokhotnyuk/play/blob/master/src/main/scala/microservice/HelloWorld.scala#L6-L7)\nand [here](https://github.com/plokhotnyuk/play/blob/master/src/main/scala/microservice/HelloWorldController.scala#L12)\n- use `sbt clean compile stage` or `sbt clean test stage` instead of just `sbt clean stage`, like in\n[this repo](https://github.com/hochgi/HTTP-stream-exercise/tree/jsoniter-2nd-round)\n- use `mill clean` if mill's native BSP support is used in IntelliJ IDEA\n- ensure that only one version of jsoniter-scala is on the classpath! Having different versions (e.g. through dependencies) will trigger this error. Use `dependencyTree`/[`dependencyGraph`](https://www.scala-sbt.org/sbt-dependency-graph) or similar mechanisms to see if this is the case. If this happens, use [exclusionRules](https://www.scala-sbt.org/1.x/docs/Library-Management.html#Exclude+Transitive+Dependencies) to get rid of the wrong versions.\n\n3. [Unexpected compiler errors](https://github.com/plokhotnyuk/jsoniter-scala/issues/551)\ncan happen during compilation of ADT definitions or their derived codecs if they are nested in some classes or functions\nlike [here](https://github.com/plokhotnyuk/jsoniter-scala/commit/db52782e6c426b73efac6c5ecaa4c28c9d128f48).\n\nThe workaround is the same for both cases: don't enclose ADT definitions into outer _classes_, _traits_ or _functions_,\nuse the outer _object_ (not a class) instead.\n\n4. Compile-time configuration for `make` calls in Scala 3 has limited support of possible expressions for name mapping.\n\nPlease use examples of `CodecMakerConfig` usage from [unit tests](https://github.com/plokhotnyuk/jsoniter-scala/blob/master/jsoniter-scala-macros/shared/src/test/scala/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodecMakerSpec.scala).   \n\n5. [Unexpected parsing or serialization errors](https://github.com/plokhotnyuk/jsoniter-scala/issues/923)\n   can happen for nested parsing or serialization routines when the same instance of `JsonReader` or `JsonWriter` is\n   reused:\n```scala\nscanJsonValuesFromStream[String](in) { s =\u003e\n  readFromString[String](s)\n}\n```\n\nThe workaround is using reentrant parsing or serialization routines for all except the most nested call. That will\ncreate a new instance of `JsonReader` or `JsonWriter` on each reentrant call:\n```scala\nscanJsonValuesFromStreamReentrant[String](in) { s =\u003e\n  readFromString[String](s)\n}\n```\n\n6. Scala.js doesn't support Java enums compiled from Java sources, so linking fails with errors like:\n```\n[error] Referring to non-existent class com.github.plokhotnyuk.jsoniter_scala.macros.Level\n[error]   called from private com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMakerSpec.$anonfun$new$24()void\n[error]   called from private com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMakerSpec.$anonfun$new$1()void\n[error]   called from constructor com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMakerSpec.\u003cinit\u003e()void\n[error]   called from static constructor com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMakerSpec.\u003cclinit\u003e()void\n[error]   called from core module analyzer\n```\n\nThe workaround for Scala 2 is to split sources for JVM and other platforms and use Java enum emulation for Scala.js and\nScala Native.\n\nCode for JVM:\n```java\npublic enum Level {\n    HIGH, LOW;\n}\n```\n\nCode for Scala.js and Scala Native:\n```scala\nobject Level {\n  val HIGH: Level = new Level(\"HIGH\", 0)\n  val LOW: Level = new Level(\"LOW\", 1)\n  \n  val values: Array[Level] = Array(HIGH, LOW)\n\n  def valueOf(name: String): Level =\n    if (HIGH.name() == name) HIGH\n    else if (LOW.name() == name) LOW\n    else throw new IllegalArgumentException(s\"Unrecognized Level name: $name\")\n}\n\nfinal class Level private (name: String, ordinal: Int) extends Enum[Level](name, ordinal)\n```\n\nFor Scala 3 the workaround can be the same for all platforms:\n```scala\nenum Level extends Enum[Level] {\n  case HIGH\n  case LOW\n}\n```\n\n7. Scala 3 compiler cannot derive anonymous codecs for generic types with concrete type parameters:\n```scala\ncase class DeResult[T](isSucceed: Boolean, data: T, message: String)\n\ncase class RootPathFiles(files: List[String])\n\ngiven JsonValueCodec[DeResult[Option[String]]] = JsonCodecMaker.make\ngiven JsonValueCodec[DeResult[RootPathFiles]] = JsonCodecMaker.make\n```\nCurrent 3.2.x versions of scalac fail with the duplicating definition error like this:\n```\n[error] 19 |      given JsonValueCodec[DeResult[RootPathFiles]] = JsonCodecMaker.make\n[error]    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n[error]    |given_JsonValueCodec_DeResult is already defined as given instance given_JsonValueCodec_DeResult\n```\nThe workaround is using named instances of codecs:\n```scala\ngiven codecOfDeResult1: JsonValueCodec[DeResult[Option[String]]] = JsonCodecMaker.make\ngiven codecOfDeResult2: JsonValueCodec[DeResult[RootPathFiles]] = JsonCodecMaker.make\n```\nor private type aliases with `given` definitions gathered in some trait:\n```scala\ntrait DeResultCodecs:\n\n  private type DeResult1 = DeResult[Option[String]]\n  private type DeResult2 = DeResult[RootPathFiles]\n\n  given JsonValueCodec[DeResult1] = JsonCodecMaker.make\n  given JsonValueCodec[DeResult2] = JsonCodecMaker.make\n\nend DeResultCodecs\n\nobject DeResultCodecs extends DeResultCodecs\n\nimport DeResultCodecs.given\n```\n\n8. Currently, the `JsonCodecMaker.make` call cannot derive codecs for Scala 3 union or complex opaque types.\nThe workaround is using a custom codec for these types defined with `implicit val` before the `JsonCodecMaker.make`\ncall, like [here](https://github.com/plokhotnyuk/jsoniter-scala/blob/7da4af1c45e11f3877708ab6d394dad9f92a3766/jsoniter-scala-macros/shared/src/test/scala-3/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodeMakerNewTypeSpec.scala#L16-L45)\nand [here](https://github.com/plokhotnyuk/jsoniter-scala/blob/7da4af1c45e11f3877708ab6d394dad9f92a3766/jsoniter-scala-macros/shared/src/test/scala-3/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodeMakerNewTypeSpec.scala#L47-L137).\n\n9. If ADT leaf classes/object contains dots in their simple names the default name mapper will strip names up to the\nlast dot character.\nThe workaround is to use `@named` annotation like here:\n```scala\nsealed abstract class Version(val value: String)\n\nobject Version {\n  @named(\"8.10\") case object `8.10` extends Version(\"8.10\")\n\n  @named(\"8.09\") case object `8.09` extends Version(\"8.9\")\n}\n```\n\n10. When parsing JSON strings to numeric or `java.time.*` values escaped encoding of ASCII characters is not supported.\nThe workaround is to use custom codecs which parse those values as strings and then convert them to corresponding types,\nlike here:\n```scala\nimplicit val customCodecOfOffsetDateTime: JsonValueCodec[OffsetDateTime] = new JsonValueCodec[OffsetDateTime] {\n  private[this] val defaultCodec: JsonValueCodec[OffsetDateTime] = JsonCodecMaker.make[OffsetDateTime]\n  private[this] val maxLen = 44 // should be enough for the longest offset date time value\n  private[this] val pool = new ThreadLocal[Array[Byte]] {\n    override def initialValue(): Array[Byte] = new Array[Byte](maxLen + 2)\n  }\n\n  def nullValue: OffsetDateTime = null\n\n  def decodeValue(in: JsonReader, default: OffsetDateTime): OffsetDateTime = {\n    val buf = pool.get\n    val s = in.readString(null)\n    val len = s.length\n    if (len \u003c= maxLen \u0026\u0026 {\n      buf(0) = '\"'\n      var bits, i = 0\n      while (i \u003c len) {\n        val ch = s.charAt(i)\n        buf(i + 1) = ch.toByte\n        bits |= ch\n        i += 1\n      }\n      buf(i + 1) = '\"'\n      bits \u003c 0x80\n    }) {\n      try {\n        return readFromSubArrayReentrant(buf, 0, len + 2, ReaderConfig)(defaultCodec)\n      } catch {\n        case NonFatal(_) =\u003e ()\n      }\n    }\n    in.decodeError(\"illegal offset date time\")\n  }\n\n  def encodeValue(x: OffsetDateTime, out: JsonWriter): Unit = out.writeVal(x)\n}\n```\n\n11. Do not use `implicit def` and `inline given` methods for generation of custom codes.\nScala 3.5.0+ shows compilation time warning `New anonymous class definition will be duplicated at each inline site`\nfor some `inline given` cases, but for other use cases the compiler will silently generate duplicated codec instances.\nTo mitigate that convert methods of codec generation to `def` and explicitly derive custom codecs, like here:\n```scala\nobject Tags {\n  opaque type Tagged[+V, +T] = Any\n\n  type @@[+V, +T] = V \u0026 Tagged[V, T]\n\n  def tag[T]: [V] =\u003e V =\u003e V @@ Tag = [V] =\u003e (v: V) =\u003e v\n}\n\nobject Graph {\n  import Tags.{@@, tag}\n\n  def tagJsonValueCodec[V, T](codec: JsonValueCodec[V]): JsonValueCodec[V @@ T] = new JsonValueCodec[V @@ T]:\n    //println(\"+1\")\n    override def decodeValue(in: JsonReader, default: V @@ T): V @@ T = tag[T](codec.decodeValue(in, default: V))\n    override def encodeValue(x: V @@ T, out: JsonWriter): Unit = codec.encodeValue(x, out)\n    override def nullValue: V @@ T = tag[T](codec.nullValue)\n\n  trait NodeIdTag\n\n  type NodeId = Int @@ NodeIdTag\n\n  case class Node(id: NodeId, name: String)\n  case class Edge(node1: NodeId, node2: NodeId)\n\n  given JsonValueCodec[Graph.NodeId] = Graph.tagJsonValueCodec(JsonCodecMaker.make)\n  given JsonValueCodec[Graph.Node] = JsonCodecMaker.make\n  given JsonValueCodec[Graph.Edge] = JsonCodecMaker.make\n}\n```\n\n## How to develop\n\nFeel free to ask questions in [chat](https://gitter.im/plokhotnyuk/jsoniter-scala), open issues, \nor contribute by creating pull requests (improvements to docs, code, and tests are highly appreciated).\n\nCurrently, the `gh-pages` branch contains a lot of historycal data of benchmark results, so to\navoid cloing 10Gb of them use `--single-branch` branch option to fetch sources only.\n\nIf developing on a fork, make sure to download the git tags (required by the sbt build):\n```sh\ngit remote add upstream git@github.com:plokhotnyuk/jsoniter-scala.git\ngit fetch --tags upstream\n```\n\nPrerequisites for building of Scala.js and Scala Native modules are Clang 18.x and Node.js 16.x.\nThe following sequence of commands works for me:\n```sh\nsudo apt install clang libstdc++-12-dev libgc-dev \ncurl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash \nsource ~/.bashrc\nnvm install 16\nnode -v\n```\n\n### Get report of available dependency updates\n\n```sh\nsbt \";dependencyUpdates; reload plugins; dependencyUpdates; reload return\"\n```\n\n### Run tests, check coverage and binary compatibility\n\n```sh\nsbt -java-home /usr/lib/jvm/jdk-11 ++2.13.18 clean coverage jsoniter-scala-coreJVM/test jsoniter-scala-circeJVM/test jsoniter-scala-macrosJVM/test jsoniter-scala-benchmarkJVM/test coverageReport\nsbt -java-home /usr/lib/jvm/jdk-11 clean +test +mimaReportBinaryIssues\n```\n\nBEWARE: jsoniter-scala is included into [Scala Community Build](https://github.com/scala/community-builds)\n for Scala 2 and [Scala Open Community Build](https://scala3.westeurope.cloudapp.azure.com/job/runBuild/) for Scala 3.\n\n### Run JVM benchmarks\n\nBefore benchmark running check if your CPU works in `performance` mode (not a `powersave` one). On Linux use following\ncommands to print current and set the `performance` mode:\n```sh\ncat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor\nfor i in $(ls /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor); do echo performance | sudo tee $i; done\n```\nThen view your CPU frequency with:\n```sh\ncat /proc/cpuinfo | grep -i mhz\n```\n\nStop un-needed applications and services. List of running services can be printed by:\n```sh\nsudo service --status-all | grep '\\[ + \\]'\nsudo systemctl list-units --state running\n```\n\nThen clear cache memory to improve system performance. One way to clear cache memory\non Linux without having to reboot the system:\n```sh\nsudo su\nfree -m -h \u0026\u0026 sync \u0026\u0026 echo 3 \u003e /proc/sys/vm/drop_caches \u0026\u0026 free -m -h\n```\n\nSbt plugin for JMH tool is used for benchmarking, to see all their features and options please check\n[Sbt-JMH docs](https://github.com/ktoso/sbt-jmh) and [JMH tool docs](https://openjdk.java.net/projects/code-tools/jmh/)\n\nLearn how to write benchmarks in [JMH samples](https://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/)\n and JMH articles posted in [Aleksey Shipilёv’s](https://shipilev.net/) and [Nitsan Wakart’s](https://psy-lob-saw.blogspot.com/p/jmh-related-posts.html)\n blogs.\n\nList of available options can be printed by:\n```sh\nsbt jsoniter-scala-benchmarkJVM/clean 'jsoniter-scala-benchmarkJVM/Jmh/run -h'\n```\n\nResults of benchmark can be stored in different formats: *.csv, *.json, etc. All supported formats can be listed by:\n```sh\nsbt jsoniter-scala-benchmarkJVM/clean 'jsoniter-scala-benchmarkJVM/Jmh/run -lrf'\n```\n\nJMH allows running benchmarks with different profilers, to get a list of supported use (can require entering of user\npassword):\n```sh\nsbt jsoniter-scala-benchmarkJVM/clean 'jsoniter-scala-benchmarkJVM/Jmh/run -lprof'\n```\n\nHelp for profiler options can be printed by following command (`\u003cprofiler_name\u003e` should be replaced by the name of the\nsupported profiler from the command above):\n```sh\nsbt jsoniter-scala-benchmarkJVM/clean 'jsoniter-scala-benchmarkJVM/Jmh/run -prof \u003cprofiler_name\u003e:help'\n```\n\nFor parametrized benchmarks the constant value(s) for parameter(s) can be set by `-p` option:\n```sh\nsbt jsoniter-scala-benchmarkJVM/clean 'jsoniter-scala-benchmarkJVM/Jmh/run -p size=1,10,100,1000 ArrayOf.*'\n```\n\nTo see throughput with the allocation rate of generated codecs run benchmarks with GC profiler using the following\ncommand:\n```sh\nsbt jsoniter-scala-benchmarkJVM/clean 'jsoniter-scala-benchmarkJVM/Jmh/run -prof gc .*Reading.*'\n```\n\nResults that are stored in JSON can be easy plotted in [JMH Visualizer](https://jmh.morethan.io/) by drugging \u0026 dropping\nof your file to the drop zone or using the `source` parameter with an HTTP link to your file in the URL like\n[here](https://jmh.morethan.io/?source=https://plokhotnyuk.github.io/jsoniter-scala/oraclejdk11.json).\n\nOn Linux the perf profiler can be used to see CPU event statistics normalized per ops:\n```sh\nsbt jsoniter-scala-benchmarkJVM/clean 'jsoniter-scala-benchmarkJVM/Jmh/run -prof perfnorm TwitterAPIReading.jsoniterScala'\n```\n\nAlso, it can be run with a specified list of events. Here is an example of benchmarking using 16 threads to check of CPU\nstalls: \n```sh\nsbt jsoniter-scala-benchmarkJVM/clean 'jsoniter-scala-benchmarkJVM/Jmh/run -t 16 -prof \"perfnorm:event=cycles,instructions,uops_executed.core,uops_executed.stall_cycles,cache-references,cache-misses,cycle_activity.stalls_total,cycle_activity.stalls_mem_any,cycle_activity.stalls_l3_miss,cycle_activity.stalls_l2_miss,cycle_activity.stalls_l1d_miss\" .*'\n```\n\nList of available events for the perf profiler can be retrieved by the following command:\n```sh\nperf list\n```\n\nTo get a result for some benchmarks with an in-flight recording file from JFR profiler use command like this:\n```sh\nsbt jsoniter-scala-benchmarkJVM/clean 'jsoniter-scala-benchmarkJVM/Jmh/run -prof \"jfr:dir=target/jfr-reports\" -wi 10 -i 60 TwitterAPIReading.jsoniterScala'\n```\nYou will get the profile in the `jsoniter-scala-benchmark/jvm/target/jfr-reports` directory.\n\nTo run benchmarks with recordings by [Async profiler](https://github.com/jvm-profiling-tools/async-profiler), extract\nbinaries to `/opt/async-profiler` directory and set the following runtime variables to capture kernel frames:\n```sh\nsudo sysctl kernel.perf_event_paranoid=1\nsudo sysctl kernel.kptr_restrict=0\n```\n\nThen use command like this:\n```sh\nsbt -java-home /usr/lib/jvm/jdk-21 jsoniter-scala-benchmarkJVM/clean 'jsoniter-scala-benchmarkJVM/Jmh/run -prof \"async:dir=target/async-reports;interval=1000000;output=flamegraph;libPath=/opt/async-profiler/lib/libasyncProfiler.so\" -jvmArgsAppend \"-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints\" --p size=128 -wi 5 -i 10 jsoniterScala'\n```\nNow you can open direct and reverse flame graphs in the `jsoniter-scala-benchmark/jvm/target/async-reports` directory.\n\nBeware that `-XX:+DebugNonSafepoints` can lead to incorrect report due to [a bug which was fixed only for JDK 21 currently](https://bugs.openjdk.org/browse/JDK-8201516).  \n\nTo see list of available events need to start your app or benchmark, and run `jps` command. I will show list of PIDs and\nnames for currently running Java processes. While your Java process still running launch the Async Profiler with the\n`list` option and ID of your process like here:\n```sh\n$ ~/Projects/com/github/jvm-profiling-tools/async-profiler/profiler.sh list 6924\nBasic events:\n  cpu\n  alloc\n  lock\n  wall\n  itimer\nPerf events:\n  page-faults\n  context-switches\n  cycles\n  instructions\n  cache-references\n  cache-misses\n  branches\n  branch-misses\n  bus-cycles\n  L1-dcache-load-misses\n  LLC-load-misses\n  dTLB-load-misses\n  mem:breakpoint\n  trace:tracepoint\n```\n\nFollowing command can be used to profile and print assembly code of the hottest methods, but it requires [a setup of \n`hsdis` library to make PrintAssembly feature enabled](https://builds.shipilev.net/hsdis/):\n```sh\nsbt jsoniter-scala-benchmarkJVM/clean 'jsoniter-scala-benchmarkJVM/Jmh/run -prof perfasm -wi 10 -i 10 -p size=128 BigIntReading.jsoniterScala'\n```\n\nMore info about extras, options, and ability to generate flame graphs see in [Sbt-JMH docs](https://github.com/ktoso/sbt-jmh)\n\nOther benchmarks with results for jsoniter-scala:\n- [comparison](https://github.com/kostya/benchmarks/tree/master#json) with other JSON parsers for different programming\n  languages and compilers\n- [comparison](https://github.com/simdjson/simdjson-java/pull/31) with most performant java parsers: simdjson-java, fastjson, jackson, etc.\n- [comparison](https://github.com/sirthias/borer/pull/30) with other JSON parsers for Scala mostly on samples from real\n  APIs, but with mapping to simple types only like strings and primitives and results for GraalVM EE Java8 only\n- [comparison](https://github.com/dkomanov/scala-serialization/pull/8) with the best binary parsers and serializers for\n  Scala\n- [comparison](https://github.com/saint1991/serialization-benchmark) with different binary and text serializers for \n  Scala\n- [comparison](https://github.com/tkrs/json-bench) with JSON serializers for Scala on synthetic samples\n- [comparison](https://github.com/yanns/scala-json-parsers-performance) with JSON parsers for Scala when parsing from/to\n  a string representation\n- [comparison](https://github.com/guillaumebort/mison/pull/1) with a state-of-the-art filter that by \"building\n  structural indices converts control flow into data flow, thereby largely eliminating inherently unpredictable branches\n  in the program and exploiting the parallelism available in modern processors\"\n\n### Run Scala.js benchmarks\n\nUse JDK 11+ for building of `jsoniter-scala-benchmarkJS` module for Scala 2.13 and Scala 3:\n```sh\nsbt -DassemblyJSBenchmarks -java-home /usr/lib/jvm/jdk-11 +jsoniter-scala-benchmarkJS/fullOptJS\n```\n\nThen open the list of benchmarks in a browser:\n```sh\ncd jsoniter-scala-benchmark/js\nopen scala-3-fullopt.html\nopen scala-2.13-fullopt.html\n```\n\nThen select the batch mode with storing results in a `.zip` file.\n\nUse the following command for merging unpacked results from browsers: `jq -s '[.[][]]' firefox/*.json \u003efirefox.json` \n\nThe released version of Scala.js benchmarks is available [here](https://plokhotnyuk.github.io/jsoniter-scala/scala-3-fullopt.html).\n\n### Run compilation time benchmarks\n\nUse the [circe-argonaut-compile-times](https://github.com/stephennancekivell/circe-argonaut-compile-times) project to \ncompare compilation time of jsoniter-scala for deeply nested product types with other JSON parsers like argonaut, \nplay-json, and circe in 3 modes: auto, semi-auto, and derivation.\n\nFor Scala 3 use the [scala3-compile-tests](https://github.com/pme123/scala3-compile-tests) project to compare\ncompilation time of jsoniter-scala for Scala 3 enumerations (sum types) with circe in semi-auto mode.\n\nPlease, also, see [an amazing talk from Mateusz Kubuszok](https://www.youtube.com/watch?v=scWvlO_fb78),\nco-author of [Chimney](https://github.com/scalalandio/chimney), about of different approaches in type class derivation\nand how some secret trick from jsoniter-scala can greatly speed up the most sanely way of auto-derivation that you\nwould like to re-use for derivation of your type-classes too. \n\n### Publish locally\n\nUse publishing of SNAPSHOT versions to your local artifact repositories for testing with other libraries or applications. \n\nPublish to the local Ivy repo:\n```sh\nsbt clean +publishLocal\n```\n\nPublish to the local Maven repo:\n```sh\nsbt clean +publishM2\n```\n\n### Release\n\nFor version numbering use [Recommended Versioning Scheme](https://docs.scala-lang.org/overviews/core/binary-compatibility-for-library-authors.html#recommended-versioning-scheme)\nthat is used in the Scala ecosystem.\n\nDouble-check binary and source compatibility, including behavior, and release using the following command on the\nenvironment with 16+GB of RAM:\n```sh\nsbt -java-home /usr/lib/jvm/jdk-11 -J-Xmx16g clean release\n```\n\nDo not push changes to GitHub until promoted artifacts for the new version are not available for downloading on\n[Maven Central Repository](https://repo1.maven.org/maven2/com/github/plokhotnyuk/jsoniter-scala)\nto avoid binary compatibility check failures in triggered Travis CI builds.\n\nThe last step is updating of the tag info in a [release list](https://github.com/plokhotnyuk/jsoniter-scala/releases).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplokhotnyuk%2Fjsoniter-scala","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplokhotnyuk%2Fjsoniter-scala","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplokhotnyuk%2Fjsoniter-scala/lists"}