{"id":13801524,"url":"https://github.com/json4s/json4s","last_synced_at":"2025-05-14T22:06:41.812Z","repository":{"id":4396627,"uuid":"5533742","full_name":"json4s/json4s","owner":"json4s","description":"JSON library","archived":false,"fork":false,"pushed_at":"2025-05-05T23:37:56.000Z","size":3879,"stargazers_count":1488,"open_issues_count":170,"forks_count":331,"subscribers_count":63,"default_branch":"master","last_synced_at":"2025-05-07T21:59:25.178Z","etag":null,"topics":["jackson","json","scala"],"latest_commit_sha":null,"homepage":"https://json4s.github.io/json4s/","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/json4s.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2012-08-23T23:18:46.000Z","updated_at":"2025-05-07T00:06:51.000Z","dependencies_parsed_at":"2023-07-06T05:55:04.915Z","dependency_job_id":"d7377499-324c-459d-b815-eecd21ff1281","html_url":"https://github.com/json4s/json4s","commit_stats":{"total_commits":1641,"total_committers":130,"mean_commits":"12.623076923076923","dds":0.5648994515539305,"last_synced_commit":"b9f953330392bfda9e95938e2a6529a2cadea625"},"previous_names":[],"tags_count":98,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/json4s%2Fjson4s","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/json4s%2Fjson4s/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/json4s%2Fjson4s/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/json4s%2Fjson4s/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/json4s","download_url":"https://codeload.github.com/json4s/json4s/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254235695,"owners_count":22036963,"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":["jackson","json","scala"],"created_at":"2024-08-04T00:01:23.871Z","updated_at":"2025-05-14T22:06:41.722Z","avatar_url":"https://github.com/json4s.png","language":"Scala","readme":"# JSON4S [![Maven Central](https://img.shields.io/maven-central/v/io.github.json4s/json4s-core_3.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:io.github.json4s%20AND%20a:json4s-core_3)\n\nAt this moment there are at least 6 json libraries for scala, not counting the java json libraries.\nAll these libraries have a very similar AST. This project aims to provide a single AST to be used by other scala\njson libraries.\n\nAt this moment the approach taken to working with the AST has been taken from lift-json and the native package\nis in fact lift-json but outside of the lift project.\n\n## Lift JSON\n\nThis project also attempts to set lift-json free from the release schedule imposed by the lift framework.\nThe Lift framework carries many dependencies and as such it's typically a blocker for many other scala projects when\na new version of scala is released.\n\nSo the native package in this library is in fact verbatim lift-json in a different package name; this means that\nyour import statements will change if you use this library.\n\n```scala\nimport org.json4s._\nimport org.json4s.native.JsonMethods._\n```\n\nAfter that everything works exactly the same as it would with lift-json\n\n## Jackson\n\nIn addition to the native parser there is also an implementation that uses jackson for parsing to the AST.\nThe jackson module includes most of the jackson-module-scala functionality and the ability to use it with the\nlift-json AST.\n\nTo use jackson instead of the native parser:\n\n```scala\nimport org.json4s._\nimport org.json4s.jackson.JsonMethods._\n```\n\nBe aware that the default behavior of the jackson integration is to close the stream when it's done.\nIf you want to change that:\n\n```scala\nimport com.fasterxml.jackson.databind.SerializationFeature\norg.json4s.jackson.JsonMethods.mapper.configure(SerializationFeature.CLOSE_CLOSEABLE, false)\n```\n\n## Guide\n\nParsing and formatting utilities for JSON.\n\nA central concept in lift-json library is Json AST which models the structure of\na JSON document as a syntax tree.\n\n```scala\nsealed abstract class JValue\ncase object JNothing extends JValue // 'zero' for JValue\ncase object JNull extends JValue\ncase class JString(s: String) extends JValue\ncase class JDouble(num: Double) extends JValue\ncase class JDecimal(num: BigDecimal) extends JValue\ncase class JInt(num: BigInt) extends JValue\ncase class JLong(num: Long) extends JValue\ncase class JBool(value: Boolean) extends JValue\ncase class JObject(obj: List[JField]) extends JValue\ncase class JArray(arr: List[JValue]) extends JValue\n\ntype JField = (String, JValue)\n```\n\nAll features are implemented in terms of the above AST. Functions are used to transform\nthe AST itself, or to transform the AST between different formats. Common transformations\nare summarized in a following picture.\n\n![Json AST](https://raw.github.com/json4s/json4s/master/core/json.png)\n\nSummary of the features:\n\n* Fast JSON parser\n* LINQ-style queries\n* Case classes can be used to extract values from parsed JSON\n* Diff \u0026 merge\n* DSL to produce valid JSON\n* XPath-like expressions and HOFs to manipulate JSON\n* Pretty and compact printing\n* XML conversions\n* Serialization\n* Low-level pull parser API\n\nInstallation\n============\n\nYou can add the json4s as a dependency in following ways. Note, replace {latestVersion} with correct Json4s version.\n\nYou can find available versions here:\n\nhttps://search.maven.org/search?q=org.json4s\n\n### SBT users\n\nFor the native support add the following dependency to your project description:\n\n```scala\nval json4sNative = \"org.json4s\" %% \"json4s-native\" % \"{latestVersion}\"\n```\n\nFor the Jackson support add the following dependency to your project description:\n\n```scala\nval json4sJackson = \"org.json4s\" %% \"json4s-jackson\" % \"{latestVersion}\"\n```\n\n### Maven users\n\nFor the native support add the following dependency to your pom:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.json4s\u003c/groupId\u003e\n  \u003cartifactId\u003ejson4s-native_${scala.version}\u003c/artifactId\u003e\n  \u003cversion\u003e{latestVersion}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nFor the jackson support add the following dependency to your pom:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.json4s\u003c/groupId\u003e\n  \u003cartifactId\u003ejson4s-jackson_${scala.version}\u003c/artifactId\u003e\n  \u003cversion\u003e{latestVersion}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nExtras\n------\n\n* [ext](https://github.com/json4s/json4s/tree/master/ext)\n\nSupport for Enum, Joda-Time, Java 8 Date \u0026 Time...\n\n* [scalaz](https://github.com/json4s/json4s/tree/master/scalaz)\n\nApplicative style parsing with Scalaz\n\n\nParsing JSON\n============\n\nAny valid json can be parsed into internal AST format.\nFor native support:\n\n```scala\nscala\u003e import org.json4s._\nscala\u003e import org.json4s.native.JsonMethods._\n\nscala\u003e parse(\"\"\" { \"numbers\" : [1, 2, 3, 4] } \"\"\")\nres0: org.json4s.JValue =\n      JObject(List((numbers,JArray(List(JInt(1), JInt(2), JInt(3), JInt(4))))))\n\nscala\u003e parse(\"\"\"{\"name\":\"Toy\",\"price\":35.35}\"\"\", useBigDecimalForDouble = true)\nres1: org.json4s.JValue =\n      JObject(List((name,JString(Toy)), (price,JDecimal(35.35))))\n```\n\nFor jackson support:\n\n```scala\nscala\u003e import org.json4s._\nscala\u003e import org.json4s.jackson.JsonMethods._\n\nscala\u003e parse(\"\"\" { \"numbers\" : [1, 2, 3, 4] } \"\"\")\nres0: org.json4s.JValue =\n      JObject(List((numbers,JArray(List(JInt(1), JInt(2), JInt(3), JInt(4))))))\n\nscala\u003e parse(\"\"\"{\"name\":\"Toy\",\"price\":35.35}\"\"\", useBigDecimalForDouble = true)\nres1: org.json4s.JValue =\n      JObject(List((name,JString(Toy)), (price,JDecimal(35.35))))\n```\n\nProducing JSON\n==============\n\nYou can generate json in 2 modes: either in `DoubleMode` or in `BigDecimalMode`; the former will map all decimal values\ninto JDoubles, and the latter into JDecimals.\n\nFor the double mode dsl use:\n\n```scala\nimport org.json4s.JsonDSL._\n// or\nimport org.json4s.JsonDSL.WithDouble._\n```\n\nFor the big decimal mode dsl use:\n\n```scala\nimport org.json4s.JsonDSL.WithBigDecimal._\n```\n\n\nDSL rules\n---------\n\n* Primitive types map to JSON primitives.\n* Any seq produces JSON array.\n\n```scala\nscala\u003e val json = List(1, 2, 3)\n\nscala\u003e compact(render(json))\nres0: String = [1,2,3]\n```\n\n* Tuple2[String, A] produces field.\n\n```scala\nscala\u003e val json = (\"name\" -\u003e \"joe\")\n\nscala\u003e compact(render(json))\nres1: String = {\"name\":\"joe\"}\n```\n\n* ~ operator produces object by combining fields.\n\n```scala\nscala\u003e val json = (\"name\" -\u003e \"joe\") ~ (\"age\" -\u003e 35)\n\nscala\u003e compact(render(json))\nres2: String = {\"name\":\"joe\",\"age\":35}\n```\n\n* ~~ operator works the same as ~ and is useful in situations where ~ is shadowed, eg. when using Spray or akka-http.\n\n```scala\nscala\u003e val json = (\"name\" -\u003e \"joe\") ~~ (\"age\" -\u003e 35)\n\nscala\u003e compact(render(json))\nres2: String = {\"name\":\"joe\",\"age\":35}\n```\n\n* Any value can be optional. The field and value are completely removed when it doesn't have a value.\n\n```scala\nscala\u003e val json = (\"name\" -\u003e \"joe\") ~ (\"age\" -\u003e Some(35))\n\nscala\u003e compact(render(json))\nres3: String = {\"name\":\"joe\",\"age\":35}\n\nscala\u003e val json = (\"name\" -\u003e \"joe\") ~ (\"age\" -\u003e (None: Option[Int]))\n\nscala\u003e compact(render(json))\nres4: String = {\"name\":\"joe\"}\n```\n\n* Extending the dsl\n\nTo extend the dsl with your own classes you must have an implicit conversion in scope of signature:\n\n```scala\ntype DslConversion = T =\u003e JValue\n```\n\nExample\n-------\n\n```scala\nimport org.json4s._\nimport org.json4s.JsonDSL._\nimport org.json4s.jackson.JsonMethods._\n\ncase class Winner(id: Long, numbers: List[Int])\ncase class Lotto(id: Long, winningNumbers: List[Int], winners: List[Winner], drawDate: Option[java.util.Date])\n\nobject JsonExample {\n\n  val winners = List(Winner(23, List(2, 45, 34, 23, 3, 5)), Winner(54, List(52, 3, 12, 11, 18, 22)))\n  val lotto = Lotto(5, List(2, 45, 34, 23, 7, 5, 3), winners, None)\n\n  val json =\n    (\"lotto\" -\u003e\n      (\"lotto-id\" -\u003e lotto.id) ~\n      (\"winning-numbers\" -\u003e lotto.winningNumbers) ~\n      (\"draw-date\" -\u003e lotto.drawDate.map(_.toString)) ~\n      (\"winners\" -\u003e\n        lotto.winners.map { w =\u003e\n          ((\"winner-id\" -\u003e w.id) ~\n           (\"numbers\" -\u003e w.numbers))}))\n\n  def main(args: Array[String]): Unit = {\n    println(compact(render(json)))\n  }\n}\n```\n\n```scala\nscala\u003e JsonExample.main(Array.empty[String])\n{\"lotto\":{\"lotto-id\":5,\"winning-numbers\":[2,45,34,23,7,5,3],\"winners\":\n[{\"winner-id\":23,\"numbers\":[2,45,34,23,3,5]},{\"winner-id\":54,\"numbers\":[52,3,12,11,18,22]}]}}\n```\n\nThe above example produces the following pretty-printed JSON. Notice that draw-date field is not rendered since its value is None:\n\n```scala\nscala\u003e pretty(render(JsonExample.json))\n\n{\n  \"lotto\":{\n    \"lotto-id\":5,\n    \"winning-numbers\":[2,45,34,23,7,5,3],\n    \"winners\":[{\n      \"winner-id\":23,\n      \"numbers\":[2,45,34,23,3,5]\n    },{\n      \"winner-id\":54,\n      \"numbers\":[52,3,12,11,18,22]\n    }]\n  }\n}\n```\n\nMerging \u0026 Diffing\n-----------------\n\nTwo JSONs can be merged and diffed with each other.\nPlease see more examples in [MergeExamples.scala](https://github.com/json4s/json4s/blob/3.6/tests/src/test/scala/org/json4s/MergeExamples.scala) and [DiffExamples.scala](https://github.com/json4s/json4s/blob/3.6/tests/src/test/scala/org/json4s/DiffExamples.scala).\n\n```scala\nscala\u003e import org.json4s._\nscala\u003e import org.json4s.jackson.JsonMethods._\n\nscala\u003e val lotto1 = parse(\"\"\"{\n         \"lotto\":{\n           \"lotto-id\":5,\n           \"winning-numbers\":[2,45,34,23,7,5,3],\n           \"winners\":[{\n             \"winner-id\":23,\n             \"numbers\":[2,45,34,23,3,5]\n           }]\n         }\n       }\"\"\")\n\nscala\u003e val lotto2 = parse(\"\"\"{\n         \"lotto\":{\n           \"winners\":[{\n             \"winner-id\":54,\n             \"numbers\":[52,3,12,11,18,22]\n           }]\n         }\n       }\"\"\")\n\nscala\u003e val mergedLotto = lotto1 merge lotto2\n\nscala\u003e pretty(render(mergedLotto))\nres0: String =\n{\n  \"lotto\":{\n    \"lotto-id\":5,\n    \"winning-numbers\":[2,45,34,23,7,5,3],\n    \"winners\":[{\n      \"winner-id\":23,\n      \"numbers\":[2,45,34,23,3,5]\n    },{\n      \"winner-id\":54,\n      \"numbers\":[52,3,12,11,18,22]\n    }]\n  }\n}\n\nscala\u003e val Diff(changed, added, deleted) = mergedLotto diff lotto1\nchanged: org.json4s.JValue = JNothing\nadded: org.json4s.JValue = JNothing\ndeleted: org.json4s.JValue = JObject(List((lotto,JObject(List(JField(winners,\nJArray(List(JObject(List((winner-id,JInt(54)), (numbers,JArray(\nList(JInt(52), JInt(3), JInt(12), JInt(11), JInt(18), JInt(22))))))))))))))\n```\n\nQuerying JSON\n=============\n\n\"LINQ\" style\n------------\n\nJSON values can be extracted using for-comprehensions.\nPlease see more examples in [JsonQueryExamples.scala](https://github.com/json4s/json4s/blob/3.6/tests/src/test/scala/org/json4s/JsonQueryExamples.scala).\n\n```scala\nscala\u003e import org.json4s._\nscala\u003e import org.json4s.native.JsonMethods._\n\nscala\u003e val json = parse(\"\"\"\n         { \"name\": \"joe\",\n           \"children\": [\n             {\n               \"name\": \"Mary\",\n               \"age\": 5\n             },\n             {\n               \"name\": \"Mazy\",\n               \"age\": 3\n             }\n           ]\n         }\n       \"\"\")\n\nscala\u003e for {\n         JObject(child) \u003c- json\n         JField(\"age\", JInt(age))  \u003c- child\n       } yield age\nres0: List[BigInt] = List(5, 3)\n\nscala\u003e for {\n         JObject(child) \u003c- json\n         JField(\"name\", JString(name)) \u003c- child\n         JField(\"age\", JInt(age)) \u003c- child\n         if age \u003e 4\n       } yield (name, age)\nres1: List[(String, BigInt)] = List((Mary,5))\n```\n\nXPath + HOFs\n------------\n\nThe json AST can be queried using XPath-like functions. The following REPL session shows the usage of\n'\\\\', '\\\\\\\\', 'find', 'filter', 'transform', 'remove' and 'values' functions.\n\nThe example json is:\n\n```javascript\n{\n  \"person\": {\n    \"name\": \"Joe\",\n    \"age\": 35,\n    \"spouse\": {\n      \"person\": {\n        \"name\": \"Marilyn\",\n        \"age\": 33\n      }\n    }\n  }\n}\n```\n\nTranslated to DSL syntax:\n\n```scala\nscala\u003e import org.json4s._\nscala\u003e import org.json4s.native.JsonMethods._\n```\n\nor\n\n```scala\nscala\u003e import org.json4s.jackson.JsonMethods._\nscala\u003e import org.json4s.JsonDSL._\n\nscala\u003e val json: JObject =\n  (\"person\" -\u003e\n    (\"name\" -\u003e \"Joe\") ~\n    (\"age\" -\u003e 35) ~\n    (\"spouse\" -\u003e\n      (\"person\" -\u003e\n        (\"name\" -\u003e \"Marilyn\") ~\n        (\"age\" -\u003e 33)\n      )\n    )\n  )\n\nscala\u003e json \\\\ \"spouse\"\nres0: org.json4s.JValue = JObject(List(\n      (person,JObject(List((name,JString(Marilyn)), (age,JInt(33)))))))\n\nscala\u003e compact(render(res0))\nres1: String = {\"person\":{\"name\":\"Marilyn\",\"age\":33}}\n\nscala\u003e compact(render(json \\\\ \"name\"))\nres2: String = {\"name\":\"Joe\",\"name\":\"Marilyn\"}\n\nscala\u003e compact(render((json removeField { _ == JField(\"name\", JString(\"Marilyn\")) }) \\\\ \"name\"))\nres3: String = \"Joe\"\n\nscala\u003e compact(render(json \\ \"person\" \\ \"name\"))\nres4: String = \"Joe\"\n\nscala\u003e compact(render(json \\ \"person\" \\ \"spouse\" \\ \"person\" \\ \"name\"))\nres5: String = \"Marilyn\"\n\nscala\u003e json findField {\n         case JField(\"name\", _) =\u003e true\n         case _ =\u003e false\n       }\nres6: Option[org.json4s.JValue] = Some((name,JString(Joe)))\n\nscala\u003e json filterField {\n         case JField(\"name\", _) =\u003e true\n         case _ =\u003e false\n       }\nres7: List[org.json4s.JField] = List(JField(name,JString(Joe)), JField(name,JString(Marilyn)))\n\nscala\u003e json transformField {\n         case JField(\"name\", JString(s)) =\u003e (\"NAME\", JString(s.toUpperCase))\n       }\nres8: org.json4s.JValue = JObject(List((person,JObject(List(\n(NAME,JString(JOE)), (age,JInt(35)), (spouse,JObject(List(\n(person,JObject(List((NAME,JString(MARILYN)), (age,JInt(33)))))))))))))\n\nscala\u003e json.values\nres8: scala.collection.immutable.Map[String,Any] = Map(person -\u003e Map(name -\u003e Joe, age -\u003e 35, spouse -\u003e Map(person -\u003e Map(name -\u003e Marilyn, age -\u003e 33))))\n```\n\nIndexed path expressions work too and values can be unboxed using type expressions:\n\n```scala\nscala\u003e val json = parse(\"\"\"\n         { \"name\": \"joe\",\n           \"children\": [\n             {\n               \"name\": \"Mary\",\n               \"age\": 5\n             },\n             {\n               \"name\": \"Mazy\",\n               \"age\": 3\n             }\n           ]\n         }\n       \"\"\")\n\nscala\u003e (json \\ \"children\")(0)\nres0: org.json4s.JValue = JObject(List((name,JString(Mary)), (age,JInt(5))))\n\nscala\u003e (json \\ \"children\")(1) \\ \"name\"\nres1: org.json4s.JValue = JString(Mazy)\n\nscala\u003e json \\\\ classOf[JInt]\nres2: List[org.json4s.JInt#Values] = List(5, 3)\n\nscala\u003e json \\ \"children\" \\\\ classOf[JString]\nres3: List[org.json4s.JString#Values] = List(Mary, Mazy)\n```\n\nExtracting values\n=================\n\nCase classes can be used to extract values from parsed JSON. Non-existent values can be extracted into scala.Option and strings can be automatically converted into java.util.Dates.\n\nPlease see more examples in [ExtractionExampleSpec.scala](https://github.com/json4s/json4s/blob/3.6/tests/src/test/scala/org/json4s/ExtractionExamplesSpec.scala).\n\n```scala\nscala\u003e import org.json4s._\nscala\u003e import org.json4s.jackson.JsonMethods._\n\nscala\u003e implicit val formats: Formats = DefaultFormats // Brings in default date formats etc.\n\nscala\u003e case class Child(name: String, age: Int, birthdate: Option[java.util.Date])\nscala\u003e case class Address(street: String, city: String)\nscala\u003e case class Person(name: String, address: Address, children: List[Child])\n\nscala\u003e val json = parse(\"\"\"\n         { \"name\": \"joe\",\n           \"address\": {\n             \"street\": \"Bulevard\",\n             \"city\": \"Helsinki\"\n           },\n           \"children\": [\n             {\n               \"name\": \"Mary\",\n               \"age\": 5,\n               \"birthdate\": \"2004-09-04T18:06:22Z\"\n             },\n             {\n               \"name\": \"Mazy\",\n               \"age\": 3\n             }\n           ]\n         }\n       \"\"\")\n\nscala\u003e json.extract[Person]\nres0: Person = Person(joe,Address(Bulevard,Helsinki),List(Child(Mary,5,Some(Sat Sep 04 18:06:22 EEST 2004)), Child(Mazy,3,None)))\n\nscala\u003e val addressJson = json  \\ \"address\"  // Extract address object\nscala\u003e addressJson.extract[Address]\nres1: Address = Address(Bulevard,Helsinki)\n\nscala\u003e (json \\ \"children\").extract[List[Child]]  // Extract list of objects\nres2: List[Child] = List(Child(Mary,5,Some(Sat Sep 04 23:36:22 IST 2004)), Child(Mazy,3,None))\n```\n\nBy default the constructor parameter names must match json field names. However, sometimes json field names contain characters which are not allowed characters in Scala identifiers. There are two solutions for this.  (See [LottoExample.scala](https://github.com/json4s/json4s/blob/3.6/tests/src/test/scala/org/json4s/LottoExample.scala) for a bigger example.)\n\nUse back ticks:\n\n```scala\nscala\u003e case class Person(`first-name`: String)\n```\n\nUse transform function to postprocess AST:\n\n```scala\nscala\u003e case class Person(firstname: String)\nscala\u003e json transformField {\n         case (\"first-name\", x) =\u003e (\"firstname\", x)\n       }\n```\n\nIf the json field names are snake case (i.e., separated_by_underscores), but the case class uses camel case (i.e., firstLetterLowercaseAndNextWordsCapitalized), you can convert the keys during the extraction using `camelizeKeys`:\n\n```scala\nscala\u003e import org.json4s._\nscala\u003e import org.json4s.native.JsonMethods._\nscala\u003e implicit val formats: Formats = DefaultFormats\nscala\u003e val json = parse(\"\"\"{\"first_name\":\"Mary\"}\"\"\")\nscala\u003e case class Person(firstName: String)\n\nscala\u003e json.camelizeKeys.extract[Person]\nres0: Person = Person(Mary)\n```\nSee the \"Serialization\" section below for details on converting a class with camel-case fields into json with snake case keys.\n\nThe extraction function tries to find the best-matching constructor when the case class has auxiliary constructors. For instance, extracting from JSON {\"price\":350} into the following case class will use the auxiliary constructor instead of the primary constructor:\n\n```scala\nscala\u003e case class Bike(make: String, price: Int) {\n         def this(price: Int) = this(\"Trek\", price)\n       }\nscala\u003e parse(\"\"\" {\"price\":350} \"\"\").extract[Bike]\nres0: Bike = Bike(Trek,350)\n```\n\nPrimitive values can be extracted from JSON primitives or fields:\n\n```scala\nscala\u003e (json \\ \"name\").extract[String]\nres0: String = \"joe\"\n\nscala\u003e ((json \\ \"children\")(0) \\ \"birthdate\").extract[Date]\nres1: java.util.Date = Sat Sep 04 21:06:22 EEST 2004\n```\n\nDateFormat can be changed by overriding 'DefaultFormats' (or by implementing trait 'Formats'):\n\n```scala\nscala\u003e implicit val formats: Formats = new DefaultFormats {\n         override def dateFormatter = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\")\n       }\n```\n\nA JSON object can be extracted to Map[String, _] too. Each field becomes a key value pair\nin result Map:\n\n```scala\nscala\u003e val json = parse(\"\"\"\n         {\n           \"name\": \"joe\",\n           \"addresses\": {\n             \"address1\": {\n               \"street\": \"Bulevard\",\n               \"city\": \"Helsinki\"\n             },\n             \"address2\": {\n               \"street\": \"Soho\",\n               \"city\": \"London\"\n             }\n           }\n         }\"\"\")\n\nscala\u003e case class PersonWithAddresses(name: String, addresses: Map[String, Address])\nscala\u003e json.extract[PersonWithAddresses]\nres0: PersonWithAddresses(\"joe\", Map(\"address1\" -\u003e Address(\"Bulevard\", \"Helsinki\"),\n                                     \"address2\" -\u003e Address(\"Soho\", \"London\")))\n```\n\nNote that when the extraction of an `Option[_]` fails, the default behavior of `extract` is to return `None`.\nYou can make it fail with a [MappingException] by using a custom `Formats` object:\n\n```scala\nval formats: Formats = DefaultFormats.withStrictOptionParsing\n```\n\nor\n\n```scala\nval formats: Formats = new DefaultFormats {\n  override val strictOptionParsing: Boolean = true\n}\n```\n\nSame happens with collections(for example, List and Map...), the default behavior of `extract`\nis to return an empty instance of the collection. \nYou can make it fail with a [MappingException] by using a custom `Formats` object:\n\n```scala\nval formats: Formats = DefaultFormats.withStrictArrayExtraction\n```\n\nor\n\n```scala\nval formats: Formats = new DefaultFormats {\n  override val strictArrayExtraction: Boolean = true\n}\n```\n\n```scala\nval formats: Formats = DefaultFormats.withStrictMapExtraction\n```\n\nor\n\n```scala\nval formats: Formats = new DefaultFormats {\n  override val strictMapExtraction: Boolean = true\n}\n```\n\nThese settings (`strictOptionParsing`, `strictArrayExtraction` and `strictMapExtraction`) can be enabled with\n\n```scala\nval formats: Formats = DefaultFormats.strict\n```\n\nWith Json4s 3.6 and higher, `apply` functions in companion objects will be evaluated for use during extraction.  If this behavior is not desired, you can disable it using the `considerCompanionConstructors` on a custom `Formats` object:\n```scala \nval formats: Formats = new DefaultFormats { override val considerCompanionConstructors = false }\n```\n\nWhen this option is disabled, only primary and secondary constructors will be evaluated for use during extraction.\n\nHandling `null`\n-------------\n\n`null` values of `Option`s are always extracted as `None`. For other types you can control the behaviour by setting the `nullExtractionStrategy` of the `Formats` used during extraction. There are three options:\n* `Keep`: Leaves null values as they are.\n* `Disallow`: Fails extraction when a `null` value is encountered.\n* `TreatAsAbsent`: Treats `null` values as if they were not present at all.\n\nSerialization\n=============\n\nCase classes can be serialized and deserialized. Please see other examples in [SerializationExamples.scala](https://github.com/json4s/json4s/blob/3.6/tests/src/test/scala/org/json4s/native/SerializationExamples.scala).\n\n```scala\nscala\u003e import org.json4s._\nscala\u003e import org.json4s.native.Serialization\nscala\u003e import org.json4s.native.Serialization.{read, write}\n\nscala\u003e implicit val formats: Formats = Serialization.formats(NoTypeHints)\n\nscala\u003e val ser = write(Child(\"Mary\", 5, None))\n\nscala\u003e read[Child](ser)\nres1: Child = Child(Mary,5,None)\n```\n\nIf you're using jackson instead of the native one:\n\n```scala\nscala\u003e import org.json4s._\nscala\u003e import org.json4s.jackson.Serialization\nscala\u003e import org.json4s.jackson.Serialization.{read, write}\n\nscala\u003e implicit val formats: Formats = Serialization.formats(NoTypeHints)\n\nscala\u003e val ser = write(Child(\"Mary\", 5, None))\n\nscala\u003e read[Child](ser)\nres1: Child = Child(Mary,5,None)\n```\n\nSerialization supports:\n\n* Arbitrarily deep case-class graphs\n* All primitive types, including BigInt and Symbol\n* List, Seq, Array, Set and Map (note, keys of the Map must be strings: Map[String, _])\n* scala.Option\n* java.util.Date\n* Polymorphic Lists (see below)\n* Recursive types\n* Serialization of fields of a class (see below)\n* Custom serializer functions for types that are not supported (see below)\n\nIf the class contains camel-case fields (i.e: firstLetterLowercaseAndNextWordsCapitalized) but you want to produce a json string with snake casing (i.e., separated_by_underscores), you can use the `snakizeKeys` method:\n\n```scala\nscala\u003e val ser = write(Person(\"Mary\"))\nser: String = {\"firstName\":\"Mary\"}\n\nscala\u003e compact(render(parse(ser).snakizeKeys))\nres0: String = {\"first_name\":\"Mary\"}\n```\n\nSerializing polymorphic Lists\n-----------------------------\n\nType hints are required when serializing polymorphic (or heterogeneous) Lists. Serialized JSON objects\nwill get an extra field named 'jsonClass' (the name can be changed by overriding 'typeHintFieldName' from Formats).\n\n```scala\nscala\u003e trait Animal\nscala\u003e case class Dog(name: String) extends Animal\nscala\u003e case class Fish(weight: Double) extends Animal\nscala\u003e case class Animals(animals: List[Animal])\n\nscala\u003e implicit val formats: Formats = Serialization.formats(ShortTypeHints(List(classOf[Dog], classOf[Fish])))\n\nscala\u003e val ser = write(Animals(Dog(\"pluto\") :: Fish(1.2) :: Nil))\nser: String = {\"animals\":[{\"jsonClass\":\"Dog\",\"name\":\"pluto\"},{\"jsonClass\":\"Fish\",\"weight\":1.2}]}\n\nscala\u003e read[Animals](ser)\nres0: Animals = Animals(List(Dog(pluto), Fish(1.2)))\n```\n\nShortTypeHints outputs the short classname for all instances of configured objects. FullTypeHints outputs the full\nclassname. Other strategies can be implemented by extending the TypeHints trait.\n\nSerializing fields of a class\n-----------------------------\n\nTo enable serialization of fields, a single FieldSerializer can be added for each type:\n\n```scala\nimplicit val formats: Formats = DefaultFormats + FieldSerializer[WildDog]()\n```\n\nNow the type WildDog (and all subtypes) gets serialized with all its fields (+ constructor parameters).\nFieldSerializer takes two optional parameters, which can be used to intercept the field serialization:\n\n```scala\ncase class FieldSerializer[A: Manifest](\n  serializer:   PartialFunction[(String, Any), Option[(String, Any)]] = Map(),\n  deserializer: PartialFunction[JField, JField] = Map()\n)\n```\n\nThose PartialFunctions are called just before a field is serialized or deserialized. Some useful PFs to rename and ignore fields are provided:\n\n```scala\nval dogSerializer = FieldSerializer[WildDog](\n  renameTo(\"name\", \"animalname\") orElse ignore(\"owner\"),\n  renameFrom(\"animalname\", \"name\"))\n\nimplicit val formats: Formats = DefaultFormats + dogSerializer\n```\n\nSupport for renaming multiple fields is accomplished by chaining the PFs like so:\n(do not add more than one FieldSerializer per type)\n\n```json\n{\"id\": \"a244\", \"start-time\": 12314545, \"end-time\": -1}\n```\n\n```scala\ncase class Log(id: String, startTime: Long, endTime: Long)\nval logSerializer = FieldSerializer[Log](\n  renameTo(\"startTime\", \"start-time\") orElse renameTo(\"endTime\", \"end-time\"),\n  renameFrom(\"start-time\", \"startTime\") orElse renameFrom(\"end-time\", \"endTime\"))\n\nimplicit val formats: Formats = DefaultFormats + logSerializer\n```\n\nSerializing classes defined in traits, classes or methods\n------------------------------------------------\n\nWe've added support for case classes defined in a trait. But they do need custom formats. I'll explain why and then how.\n\n##### Why?\n\nFor classes defined in a trait it's a bit difficult to get to their companion object, which is needed to provide default values. We could punt on those but that brings us to the next problem, that the compiler generates an extra field in the constructor of such case classes. The first field in the constructor of those case classes is called `$outer` and is of type of the *defining trait*. So somehow we need to get an instance of that object, naively we could scan all classes and collect the ones that are implementing the trait, but when there are more than one: which one to take?\n\n##### How?\n\nI've chosen to extend the formats to include a list of companion mappings for those case classes. So you can have formats that belong to your modules and keep the mappings in there. That will then make default values work and provide the much needed `$outer` field.\n\n```scala\ntrait SharedModule {\n  case class SharedObj(name: String, visible: Boolean = false)\n}\n\nobject PingPongGame extends SharedModule\nimplicit val formats: Formats =\n  DefaultFormats.withCompanions(classOf[PingPongGame.SharedObj] -\u003e PingPongGame)\n\nval inst = PingPongGame.SharedObj(\"jeff\", visible = true)\nval extr = Extraction.decompose(inst)\nextr must_== JObject(\"name\" -\u003e JString(\"jeff\"), \"visible\" -\u003e JBool(true))\nextr.extract[PingPongGame.SharedObj] must_== inst\n```\n\nSerializing non-supported types\n-------------------------------\n\nIt is possible to plug in custom serializer + deserializer functions for any type.\nNow, if we have a non-case class Interval (thus, not supported by default), we can still serialize it\nby providing following serializer.\n\n```scala\nscala\u003e class Interval(start: Long, end: Long) {\n         val startTime = start\n         val endTime = end\n       }\n\nscala\u003e class IntervalSerializer extends CustomSerializer[Interval](format =\u003e (\n         {\n           case JObject(JField(\"start\", JInt(s)) :: JField(\"end\", JInt(e)) :: Nil) =\u003e\n             new Interval(s.longValue, e.longValue)\n         },\n         {\n           case x: Interval =\u003e\n             JObject(JField(\"start\", JInt(BigInt(x.startTime))) ::\n                     JField(\"end\",   JInt(BigInt(x.endTime))) :: Nil)\n         }\n       ))\n\nscala\u003e implicit val formats: Formats = Serialization.formats(NoTypeHints) + new IntervalSerializer\n```\n\nA custom serializer is created by providing two partial functions. The first evaluates to a value\nif it can unpack the data from JSON. The second creates the desired JSON if the type matches.\n\nExtensions\n----------\n\nModule json4s-ext contains extensions to extraction and serialization. The following types are supported.\n\n```scala\n// Scala enums\nimplicit val formats: Formats = org.json4s.DefaultFormats + new org.json4s.ext.EnumSerializer(MyEnum)\n// or\nimplicit val formats: Formats = org.json4s.DefaultFormats + new org.json4s.ext.EnumNameSerializer(MyEnum)\n\n// Joda Time\nimplicit val formats: Formats = org.json4s.DefaultFormats ++ org.json4s.ext.JodaTimeSerializers.all\n\n// Java 8 Date \u0026 Time\nimplicit val formats: Formats = org.json4s.DefaultFormats ++ org.json4s.ext.JavaTimeSerializers.all\n```\n\nXML support\n===========\n\nJSON structure can be converted to XML nodes and vice versa.\nPlease see more examples in [XmlExamples.scala](https://github.com/json4s/json4s/blob/3.6/tests/src/test/scala/org/json4s/XmlExamples.scala).\n\n```scala\nscala\u003e import org.json4s.Xml.{toJson, toXml}\nscala\u003e val xml =\n         \u003cusers\u003e\n           \u003cuser\u003e\n             \u003cid\u003e1\u003c/id\u003e\n             \u003cname\u003eHarry\u003c/name\u003e\n           \u003c/user\u003e\n           \u003cuser\u003e\n             \u003cid\u003e2\u003c/id\u003e\n             \u003cname\u003eDavid\u003c/name\u003e\n           \u003c/user\u003e\n         \u003c/users\u003e\n\nscala\u003e val json = toJson(xml)\nscala\u003e pretty(render(json))\nres3: String =\n{\n  \"users\":{\n    \"user\":[{\n      \"id\":\"1\",\n      \"name\":\"Harry\"\n    },{\n      \"id\":\"2\",\n      \"name\":\"David\"\n    }]\n  }\n}\n```\n\nNow, the above example has two problems. First, the ID is converted to String while we might want it as an Int. This is easy to fix by mapping JString(s) to JInt(s.toInt). The second problem is more subtle. The conversion function decides to use a JSON array because there's more than one `user` element in XML. Therefore a structurally equivalent XML document which happens to have just one `user` element will generate a JSON document without a JSON array. This is rarely a desired outcome. These both problems can be fixed by the following transformation function.\n\n```scala\nscala\u003e json transformField {\n         case (\"id\", JString(s)) =\u003e (\"id\", JInt(s.toInt))\n         case (\"user\", x: JObject) =\u003e (\"user\", JArray(x :: Nil))\n       }\n```\n\nOther direction is supported too. Converting JSON to XML:\n\n```scala\nscala\u003e toXml(json)\nres5: scala.xml.NodeSeq = NodeSeq(\u003cusers\u003e\u003cuser\u003e\u003cid\u003e1\u003c/id\u003e\u003cname\u003eHarry\u003c/name\u003e\u003c/user\u003e\u003cuser\u003e\u003cid\u003e2\u003c/id\u003e\u003cname\u003eDavid\u003c/name\u003e\u003c/user\u003e\u003c/users\u003e)\n```\n\nLow-level pull parser API\n=========================\n\nThe pull parser API is provided for cases requiring extreme performance. It improves parsing performance in two ways. First, no intermediate AST is generated. Second, you can stop parsing at any time, skipping the rest of the stream. Note:  This parsing style is recommended only as an optimization. The above-mentioned functional APIs are easier to use.\n\nConsider the following example, which shows how to parse one field value from a big JSON:\n\n```scala\nscala\u003e val json = \"\"\"\n  {\n    ...\n    \"firstName\": \"John\",\n    \"lastName\": \"Smith\",\n    \"address\": {\n      \"streetAddress\": \"21 2nd Street\",\n      \"city\": \"New York\",\n      \"state\": \"NY\",\n      \"postalCode\": 10021\n    },\n    \"phoneNumbers\": [\n      { \"type\": \"home\", \"number\": \"212 555-1234\" },\n      { \"type\": \"fax\", \"number\": \"646 555-4567\" }\n    ],\n    ...\n  }\"\"\"\n\nscala\u003e val parser = (p: Parser) =\u003e {\n         def parse: BigInt = p.nextToken match {\n           case FieldStart(\"postalCode\") =\u003e p.nextToken match {\n             case IntVal(code) =\u003e code\n             case _ =\u003e p.fail(\"expected int\")\n           }\n           case End =\u003e p.fail(\"no field named 'postalCode'\")\n           case _ =\u003e parse\n         }\n\n         parse\n       }\n\nscala\u003e val postalCode = parse(json, parser)\npostalCode: BigInt = 10021\n```\n\nThe pull parser is a function `Parser =\u003e A`; in this example it is concretely `Parser =\u003e BigInt`.\nThe constructed parser recursively reads tokens until it finds a `FieldStart(\"postalCode\")` token.\nAfter that the next token must be `IntVal`; otherwise parsing fails. It returns the parsed integer value and stops parsing immediately.\n\nKudos\n=====\n\n* The original idea for the DSL syntax was taken from the Lift mailing list ([by Marius](http://markmail.org/message/lniven2hn22vhupu)).\n\n* The idea for the AST and rendering was taken from [Real World Haskell book](http://book.realworldhaskell.org/read/writing-a-library-working-with-json-data.html).\n","funding_links":[],"categories":["Table of Contents","JSON","JSON Manipulation"],"sub_categories":["JSON"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjson4s%2Fjson4s","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjson4s%2Fjson4s","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjson4s%2Fjson4s/lists"}