Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala - parse json of more than 22 elements into case class

Tags:

json

scala

This question or similar ones were posted before, however none of the solutions work any more with latest libraries. After extensive searching as of now I found no evidence that latest versions of most popular libraries spray-json or play-json (or their plugins) can handle this case. Is there something that can parse a json of more than 22 elements into scala case class? Since scala 2.11 case classes are no longer limited to 22 elements. Please, only fully working solutions. Obvious json example below.

{
    "a": 1,
    "b": 2,
    "c": 3,
    "d": 4,
    "e": 5,
    "f": 6,
    "g": 7,
    "h": 8,
    "i": 9,
    "j": 10,
    "k": 11,
    "l": 12,
    "m": 13,
    "n": 14,
    "o": 15,
    "p": 16,
    "q": 17,
    "r": 18,
    "s": 19,
    "t": 20,
    "u": 21,
    "v": 22,
    "w": 23
}

UPDATE: This is a case when you have no control over json structure, for instance it's retrieved from a 3rd party api. An example of twitter's tweet json: http://pastebin.com/h8fHAsd8

like image 303
Caballero Avatar asked Oct 24 '15 13:10

Caballero


3 Answers

circe does, with automatic codec derivation supported by Shapeless. Note that unlike json4s's case class decoding, there's no runtime reflection happening here:

case class Foo(
  a: Int, b: Int, c: Int, d: Int, e: Int, f: Int, g: Int, h: Int, i: Int,
  j: Int, k: Int, l: Int, m: Int, n: Int, o: Int, p: Int, q: Int, r: Int,
  s: Int, t: Int, u: Int, v: Int, w: Int
)

import io.circe.generic.auto._, io.circe.jawn.decode

val json = """{
  "a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9,
  "j": 10, "k": 11, "l": 12, "m": 13, "n": 14, "o": 15, "p": 16, "q": 17,
  "r": 18, "s": 19, "t": 20, "u": 21, "v": 22, "w": 23
}"""

val result: cats.data.Xor[io.circe.Error, Foo] = decode[Foo](json)

Here's a minimal build.sbt file:

scalaVersion := "2.11.7"

addCompilerPlugin(
  "org.scalamacros" % "paradise" % "2.1.0-M5" cross CrossVersion.full
)

libraryDependencies ++= Seq(
  "io.circe" %% "circe-core" % "0.1.1",
  "io.circe" %% "circe-generic" % "0.1.1",
  "io.circe" %% "circe-jawn" % "0.1.1"
)

The upcoming 0.2.0 release (currently available as a snapshot) includes a lot of improvements to generic derivation, but for a simple example like this the 0.1.1 behavior is the same.

like image 172
Travis Brown Avatar answered Oct 21 '22 01:10

Travis Brown


For play-json, the play-json-extensions offer an extension that supports >22 fields and a few other use cases like serializing sealed trait structures, singleton objects, etc.

import org.cvogt.play.json.Jsonx
implicit val jsonFormat = Jsonx.formatCaseClass[Foo] // Instead of Json.format

https://github.com/cvogt/play-json-extensions

circe/argonaut is certainly worth checking out as well. Not sure about how they compare in terms of features and stability compared to play-json/play-json-extensions.

like image 2
cvogt Avatar answered Oct 21 '22 02:10

cvogt


Inspired by @cvogt and other my personal requirements I've develop a library to manage transparently via macro the > 22 fields and other features.

The library is here and documentation

The JsonFormat annotation creates via macro a "pimped" json format that manage a lot of stuff.

Main Features are:

  • Play JSON for ScalaJS
  • JsonFormat macro annotation for lazy people
  • Default field values populated in missing JSON
  • Field rewrite for Play JSON ("key")
  • +22 field case class formatter and more Play Json Extension
  • Joda Datetime for Scala and ScalaJS
  • Strong Typed Enum (String and Int) for Scala and ScalaJS
  • Variant Types
like image 2
aparo Avatar answered Oct 21 '22 01:10

aparo