{"id":25053724,"url":"https://github.com/hypertino/json-binders","last_synced_at":"2026-03-02T15:33:53.177Z","repository":{"id":57725087,"uuid":"68479078","full_name":"hypertino/json-binders","owner":"hypertino","description":"Json serializer for Scala/Scala.JS","archived":false,"fork":false,"pushed_at":"2020-01-15T11:31:41.000Z","size":218,"stargazers_count":2,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-07T06:46:58.936Z","etag":null,"topics":["json","macro","scala","scalajs","serialization-library"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hypertino.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-09-17T21:25:55.000Z","updated_at":"2021-03-21T04:24:42.000Z","dependencies_parsed_at":"2022-09-08T04:10:27.608Z","dependency_job_id":null,"html_url":"https://github.com/hypertino/json-binders","commit_stats":null,"previous_names":["hypertino/binders-json"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hypertino/json-binders","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypertino%2Fjson-binders","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypertino%2Fjson-binders/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypertino%2Fjson-binders/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypertino%2Fjson-binders/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hypertino","download_url":"https://codeload.github.com/hypertino/json-binders/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypertino%2Fjson-binders/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28314256,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T14:58:17.114Z","status":"ssl_error","status_checked_at":"2026-01-11T14:55:53.580Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["json","macro","scala","scalajs","serialization-library"],"created_at":"2025-02-06T11:51:01.597Z","updated_at":"2026-01-11T17:01:24.271Z","avatar_url":"https://github.com/hypertino.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/hypertino/json-binders.svg)](https://travis-ci.org/hypertino/json-binders)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.hypertino/json-binders_2.13/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.hypertino/json-binders_2.13)\n\n[ Latest releases and snapshots](https://oss.sonatype.org/#nexus-search;gav~com.hypertino~json-binders_*~~~)\n\n# json-binders\n\n`json-binders` is a library for Scala/Scala.js that allows you to serialize/deserialize Scala case classes, primitive types to/from JSON representation.\n\n## Why json-binders?\n\nThere already exists a numerous libraries for the same purpose, like `scala/pickling`, `upickle`, `spray-json` targeting Scala and `FasterXML/jackson`, `gson` and many others Java libraries that you may use in Scala.\n\nKey features of `json-binders` are:\n\n1. Compile-time code generation without runtime reflection\n2. Streaming/iterative underlying API\n3. Clean/interoperable JSON format\n4. Schemaless fields support\n5. Scala.js support\n\nThe most close alternative is a [uPickle](http://www.lihaoyi.com/upickle-pprint/upickle/), and the most notable differences that `json-binders` gives you are:\n\n1. 2-3 times performance boost, see below on performance benchmark\n2. ability to work with schemaless fields (`Value` type)\n3. `FasterXML/jackson` dependency for JVM compilation instead of `Jaws` that is used by `uPickle`\n4. `uPickle` serializes `Option[Something]` as array, while in `json-binders` it's serialized as a regular field.\n\n# Download\n\nAdd to project with SBT: `\"com.hypertino\" %% \"json-binders\" % \"1.0-SNAPSHOT\"`\n\n# Quickstart\n\nA plain example on how-to start using a library:\n\n```scala\ncase class Crocodile(\n  name: String,\n  length: Int,\n  color: Option[String]\n)\n\nimport com.hypertino.binders.json.JsonBinders._\n\nval crocodileJson = Crocodile(\"Gena\", 250, Some(\"Green\")).toJson\n\n// crocodileJson: String = {\"name\":\"Gena\",\"length\":250,\"color\":\"Green\"}\n\nval crocodile = crocodileJson.parseJson[Crocodile]\n```\n\nThat's it. If you work with string representation of JSON then you only have to use `toJson`/`parseJson` macro calls. \n\n# Supported types\n\n### Primitive types\n\n`json-binders` supports primitive types: `Int`, `Long`, `Double`, `Float`, `BigDecimal` and `Boolean` with `String`.\n\u003e Please note that `Long` range is limited due to fact that Javascript's Number type (64 bit IEEE 754) only has about 53 bits of precision\n\n\n### `Duration` and `FiniteDuration`\n`Duration` and `FiniteDuration` are supported out of box. `Duration` is serialized as a string value and `FiniteDuration` as a numeric value in milliseconds. \n    \n### Case-classes and normal classes/traits with companion object\n\nAs it shown in an example the case-classes are supported out of box. Any regular class or a trait that have a companion object with corresponding `apply`/`unaply` methods are supported as well.\n\n#### Default case class values\n\nCase-classes can have default values specified on fields. And `json-binders` will return default field value in case if JSON source doesn't contains that field or the value of the field is `null`.  \nExample:\n\n```scala\ncase class Zoo(\n  name: String,\n  open: Boolean = true\n)\n\nval zoo = \"\"\"{\"name\":\"Moscow Zoo\"}\"\"\".parseJson[Zoo]\n// zoo.open is true here\n```\n\n#### Case-class field names\n\nIf you need a special name on some field, you may set it with an attribute `fieldName`:\nExample:\n\n```scala\ncase class Kid(\n  @fieldName(\"name of kid\") name: String, \n  age: Int\n)\n\nKid(\"John\", 13).toJson // produces: {\"name of kid\":\"John\",\"age\":13}\n```\n\n## Collections\n\nYou can read and write almost any Scala collection class.\n```\nList(1,2,3).toJson // produces `[1,2,3]` \n\n\"[1,2,3]\".parseJson[List[Int]] // produces List[Int] = List(1, 2, 3) \n\n// more complex case:\nList(Kid(\"John\", 13), Kid(\"Anthony\", 12), Kid(\"Ellie\", 13)).toJson\n```\nAll collection items have to be bindable (primitive or a case-class or collection, etc). \nIn general any collection that implements `canBuildFrom` is supported.\n\n### `Map[String, Something]`\n\n`Map[String, Something]` is a special case and it is serialized as a JSON object. The `Something` here can be any bindable type.\n\n## null handling\n\nIf a field is defined as `Option[Something]` then null value is deserialized as None and vice versa.\n \nIf a field can't be null, like `Int` or any other primitive value, an exception will be thrown while reading `null` value.   \n\n## Either\n\n`json-binders` tries to find best matching data type when reading `Either[_,_]`\n\n```scala\n\"1\".parseJson[Either[Int,String]] // returns Left(1)\n```\n\nMore complex scenarios are possible with collections and objects.\n\n## Custom types\n\nYou may support any custom type implementing `ImplicitSerializer` and `ImplicitDeserializer` traits.\n\nExample:\n\n```scala\nclass InstantTypeSerializer extends ImplicitSerializer[Instant, JsonSerializer[_]] {\n  override def write(serializer: JsonSerializer[_], value: Instant): Unit = serializer.writeLong(value.toEpochMilli)\n}\n\nclass InstantTypeDeserializer extends ImplicitDeserializer[Instant, JsonDeserializer[_]] {\n  override def read(deserializer: JsonDeserializer[_]): Instant = Instant.ofEpochMilli(deserializer.readLong())\n}\n\nobject InstantJsonBinders {\n  implicit val serializer = new InstantTypeSerializer\n  implicit val deserializer = new InstantTypeDeserializer\n}\n\nimport JsonBinders._\nimport InstantJsonBinders._\n\nval instantJson = Instant.parse(\"2016-10-01T00:12:42.007Z\").toJson\n// instantJson: String = 1475280762007\n\nval instant = instantJson.parseJson[Instant]\n// instant: org.threeten.bp.Instant = 2016-10-01T00:12:42.007Z\n```\n\n## Schemaless/custom fields\n\n`binders` library provides a `Value` type that:\n\n- Implements the [`scala.Dynamic`](http://www.scala-lang.org/api/current/index.html#scala.Dynamic) to access object fields using dynamic invocation\n- Can be a `Null`, `Obj`, `Lst`, `Text`, `Number` or `Bool`\n- Guarantees that it's serializable to JSON\n- Provides a `visitor pattern` interface to `Value` tree\n\nOne of the examples of using `Value` is when you need some custom, schema-free data inside some class. Example:\n\n```scala\nimport com.hypertino.binders.value._\n\ncase class Crocodile(\n  name: String,\n  color: Option[String],\n  extra: Value          // \u003c- custom extra data stored here\n)\n\nimport com.hypertino.binders.json.JsonBinders._\n\nval crocodileJson = Crocodile(\"Gena\", Some(\"Green\"), \n  Obj.from(\"country\" -\u003e \"Russia\", \"age\" -\u003e 49) // this constructs Obj type for extra field\n).toJson\n\n// crocodileJson: String = {\"name\":\"Gena\",\"color\":\"Green\",\"extra\":{\"country\":\"Russia\",\"age\":49}}\n\nval crocodile = crocodileJson.parseJson[Crocodile]\n\nval country = crocodile.extra.country // accessing field through `scala.Dynamic` \nprintln(country.toString)\n\nval age = crocodile.extra.age // returned type is `Value` instance type `Number`\nprintln(age.toInt)\n```\n\n# Benchmark\n\nBenchmark results here are gathered on Macbook Pro Core i5 2.5GHz. I'm comparing `json-binders` with `uPickle 0.4.1`.\n\n## JVM benchmark\n\nJVM benchmark is done with OpenJDK jmh tool. To validate results run `sbt 'benchTestJVM/jmh:run'`\n\n```\nJsonBindersBenchmark.Binders_deserializeCaseClass                       thrpt  200   610167,407 ± 4217,269  ops/s\nJsonBindersBenchmark.Binders_deserializeCaseClass2                      thrpt  200    46471,465 ±  299,064  ops/s\nJsonBindersBenchmark.Binders_serializeAndDeserializeCaseClass           thrpt  200   306330,001 ± 2027,039  ops/s\nJsonBindersBenchmark.Binders_serializeAndDeserializeCaseClass2          thrpt  200    31640,815 ±  165,431  ops/s\nJsonBindersBenchmark.Binders_serializeAndDeserializeCaseClass2NoOption  thrpt  200    25878,555 ±  128,021  ops/s\nJsonBindersBenchmark.Binders_serializeCaseClass                         thrpt  200  1082355,813 ± 5263,266  ops/s\nJsonBindersBenchmark.Binders_serializeCaseClass2                        thrpt  200   103028,012 ±  441,978  ops/s\n\nJsonBindersBenchmark.Upickle_deserializeCaseClass                       thrpt  200   203965,085 ± 1693,887  ops/s\nJsonBindersBenchmark.Upickle_deserializeCaseClass2                      thrpt  200    22248,249 ±  282,005  ops/s\nJsonBindersBenchmark.Upickle_serializeAndDeserializeCaseClass           thrpt  200   111382,834 ±  542,432  ops/s\nJsonBindersBenchmark.Upickle_serializeAndDeserializeCaseClass2          thrpt  200    13816,731 ±  123,517  ops/s\nJsonBindersBenchmark.Upickle_serializeAndDeserializeCaseClass2NoOption  thrpt  200    15366,293 ±  161,253  ops/s\nJsonBindersBenchmark.Upickle_serializeCaseClass                         thrpt  200   410833,045 ± 2858,354  ops/s\nJsonBindersBenchmark.Upickle_serializeCaseClass2                        thrpt  200    40894,468 ±  245,502  ops/s\n```\n\n## JS benchmark\n\nJS benchmark is more naive and straitforward. It's done with `node v6.3.0` and `fullOptJS` option enabled. To execute benchmark run `sbt 'benchTestJS/run'`\n\n```\nBinders_serializeCaseClass                             299001.4286 ops/sec. 2093010 cnt for 7000 ms\nBinders_deserializeCaseClass                            26036.4205 ops/sec. 183010 cnt for 7029 ms\nBinders_serializeAndDeserializeCaseClass                21526.7284 ops/sec. 151010 cnt for 7015 ms\nBinders_serializeCaseClass2                             27178.4291 ops/sec. 191010 cnt for 7028 ms\nBinders_deserializeCaseClass2                            2473.9011 ops/sec. 18010 cnt for 7280 ms\nBinders_serializeAndDeserializeCaseClass2                2220.2191 ops/sec. 16010 cnt for 7211 ms\nBinders_serializeAndDeserializeCaseClass2NoOption        1710.0055 ops/sec. 12442 cnt for 7276 ms\n\nUpickle_serializeCaseClass                              35537.3198 ops/sec. 249010 cnt for 7007 ms\nUpickle_deserializeCaseClass                            20819.9059 ops/sec. 146010 cnt for 7013 ms\nUpickle_serializeAndDeserializeCaseClass                11695.6646 ops/sec. 82010 cnt for 7012 ms\nUpickle_serializeCaseClass2                              4985.0491 ops/sec. 35010 cnt for 7023 ms\nUpickle_deserializeCaseClass2                            2419.2860 ops/sec. 17010 cnt for 7031 ms\nUpickle_serializeAndDeserializeCaseClass2                1610.0759 ops/sec. 11665 cnt for 7245 ms\nUpickle_serializeAndDeserializeCaseClass2NoOption        2022.3135 ops/sec. 14773 cnt for 7305 ms\n```\n\n# Additional serializers\n\n[soc-time](https://github.com/soc/scala-java-time) is a Scala.JS compatible Java8 time implementation.\n\nAdd to project with SBT: `\"com.hypertino\" %% \"json-time-binders\" % \"1.0-SNAPSHOT\"`. See an example in [TestInstantSerializer.scala](jsonTimeBinders/shared/src/test/scala/TestInstantSerializer.scala)\n\n# Things to cover\n\n- naming convention converters;\n- stream API;\n- iterator/stream/seq shortcomings;\n\n# License\n\n`json-binders` is licensed under BSD 3-clause as stated in file LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhypertino%2Fjson-binders","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhypertino%2Fjson-binders","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhypertino%2Fjson-binders/lists"}