Skip to content
Commits on Source (3)
language: scala
scala:
- 2.10.6
- 2.11.8
matrix:
include:
- scala: 2.12.1
jdk: oraclejdk8
sudo: false
cache:
directories:
- $HOME/.ivy2/cache
- $HOME/.sbt/boot/scala-$TRAVIS_SCALA_VERSION
before_install:
- export TZ=Australia/Canberra
script:
#- travis_retry sbt ++$TRAVIS_SCALA_VERSION mimaReportBinaryIssues test
- travis_retry sbt ++$TRAVIS_SCALA_VERSION javaVersionCheck test
- find $HOME/.sbt -name "*.lock" | xargs rm
- find $HOME/.ivy2 -name "ivydata-*.properties" | xargs rm
addons:
apt:
packages:
- oracle-java8-installer
see https://github.com/json4s/json4s/blob/3.6/CONTRIBUTING.md
This diff is collapsed.
......@@ -58,8 +58,6 @@ object Diff {
case (x, y) if x == y => Diff(JNothing, JNothing, JNothing)
case (JObject(xs), JObject(ys)) => diffFields(xs, ys)
case (JArray(xs), JArray(ys)) => diffVals(xs, ys)
// unlike diff of JArrays, order of elements is ignored in diff of JSets
case (JSet(x), JSet(y)) if (JSet(x) != (JSet(y))) => Diff(JNothing, JSet(y).difference(JSet(x)), JSet(x).difference(JSet(y)))
case (JInt(x), JInt(y)) if (x != y) => Diff(JInt(y), JNothing, JNothing)
case (JDouble(x), JDouble(y)) if (x != y) => Diff(JDouble(y), JNothing, JNothing)
case (JDecimal(x), JDecimal(y)) if (x != y) => Diff(JDecimal(y), JNothing, JNothing)
......
......@@ -16,6 +16,10 @@
package org.json4s
import java.util.Locale.ENGLISH
import java.io.StringWriter
import collection.immutable
object JsonAST {
/**
......@@ -27,12 +31,60 @@ object JsonAST {
*/
def concat(xs: JValue*) = xs.foldLeft(JNothing: JValue)(_ ++ _)
// sealed abstract class JsValue[+T] extends immutable.Seq[T] {
// def values: T
// }
// private trait SingleElementJsValue[+T] extends JsValue[T] {
// def length: Int = 1
// def apply(idx: Int): T = if (idx == 0) values else throw new IndexOutOfBoundsException("A JsString only has 1 element")
// def iterator: Iterator[T] = Iterator(values)
// override def isEmpty: Boolean = false
// override def head = values
// override def tail: immutable.Seq[T] = Nil
// override protected[this] def reversed: List[T] = List(values)
// override def nonEmpty: Boolean = true
// }
//
// class JsString(val values: String) extends SingleElementJsValue[String]
// class JsInt(val values: BigInt) extends SingleElementJsValue[BigInt]
// class JsDecimal(val values: BigDecimal) extends SingleElementJsValue[BigDecimal]
// class JsBool(val values: Boolean) extends SingleElementJsValue[Boolean]
// object JsNull extends SingleElementJsValue[Null] { val values: Null = null }
//
// class JsObject(val values: Seq[(String, JsValue[_])]) extends JsValue[(String, JsValue[_])] {
// def length: Int = values.length
// def apply(idx: Int): (String, JsValue[_]) = values(idx)
// def iterator: Iterator[(String, JsValue[_])] = values.iterator
// }
// class JsArray(val values: Seq[JsValue[_]]) extends JsValue[JsValue[_]] {
// def length: Int = values.length
// def apply(idx: Int): JsValue[_] = values.apply(idx)
// def iterator: Iterator[JsValue[_]] = values.iterator
// }
// object JsNothing extends JsValue[Nothing] {
// val values: Nothing = null.asInstanceOf[Nothing]
// val length: Int = 0
// def apply(idx: Int): Nothing = throw new IndexOutOfBoundsException("A JsNothing is empty")
// def iterator: Iterator[Nothing] = Iterator()
//
// override def isEmpty = true
// override def head: Nothing =
// throw new NoSuchElementException("head of JsNothing")
// override def tail: List[Nothing] =
// throw new UnsupportedOperationException("tail of JsNothing")
// // Removal of equals method here might lead to an infinite recursion similar to IntMap.equals.
// override def equals(that: Any) = that match {
// case that1: JsValue[_] => that1.isEmpty
// case _ => false
// }
// }
object JValue extends Merge.Mergeable
/**
* Data type for JSON AST.
*/
sealed abstract class JValue extends Diff.Diffable with Product with Serializable {
sealed abstract class JValue extends Diff.Diffable {
type Values
......@@ -138,10 +190,6 @@ object JsonAST {
type Values = BigDecimal
def values = num
}
case class JLong(num: Long) extends JValue with JNumber {
type Values = Long
def values = num
}
case class JInt(num: BigInt) extends JValue with JNumber {
type Values = BigInt
def values = num
......@@ -150,10 +198,6 @@ object JsonAST {
type Values = Boolean
def values = value
}
object JBool {
val True = JBool(true)
val False = JBool(false)
}
case class JObject(obj: List[JField]) extends JValue {
type Values = Map[String, Any]
......@@ -176,23 +220,6 @@ object JsonAST {
override def apply(i: Int): JValue = arr(i)
}
// JSet is set implementation for JValue.
// It supports basic set operations, like intersection, union and difference.
case class JSet(set: Set[JValue]) extends JValue {
type Values = Set[JValue]
def values = set
override def equals(o: Any): Boolean = o match {
case o: JSet o.values == values
case _ false
}
def intersect(o: JSet): JSet = JSet(o.values.intersect(values))
def union(o: JSet): JSet = JSet(o.values.union(values))
def difference(o: JSet): JSet = JSet(values.diff(o.values))
}
type JField = (String, JValue)
object JField {
def apply(name: String, value: JValue) = (name, value)
......
......@@ -41,9 +41,6 @@ trait DoubleMode { self: Implicits ⇒
}
object DoubleMode extends Implicits with DoubleMode
trait Implicits {
implicit def short2jvalue(x: Short): JValue = JInt(x)
implicit def byte2jvalue(x: Byte): JValue = JInt(x)
implicit def char2jvalue(x: Char): JValue = JInt(x)
implicit def int2jvalue(x: Int): JValue = JInt(x)
implicit def long2jvalue(x: Long): JValue = JInt(x)
implicit def bigint2jvalue(x: BigInt): JValue = JInt(x)
......@@ -67,25 +64,25 @@ object JsonDSL extends JsonDSL with DoubleMode {
}
trait JsonDSL extends Implicits {
implicit def seq2jvalue[A](s: Traversable[A])(implicit ev: A => JValue) =
implicit def seq2jvalue[A <% JValue](s: Traversable[A]) =
JArray(s.toList.map { a val v: JValue = a; v })
implicit def map2jvalue[A](m: Map[String, A])(implicit ev: A => JValue) =
implicit def map2jvalue[A <% JValue](m: Map[String, A]) =
JObject(m.toList.map { case (k, v) JField(k, v) })
implicit def option2jvalue[A](opt: Option[A])(implicit ev: A => JValue): JValue = opt match {
implicit def option2jvalue[A <% JValue](opt: Option[A]): JValue = opt match {
case Some(x) x
case None JNothing
}
implicit def symbol2jvalue(x: Symbol) = JString(x.name)
implicit def pair2jvalue[A](t: (String, A))(implicit ev: A => JValue) = JObject(List(JField(t._1, t._2)))
implicit def pair2jvalue[A <% JValue](t: (String, A)) = JObject(List(JField(t._1, t._2)))
implicit def list2jvalue(l: List[JField]) = JObject(l)
implicit def jobject2assoc(o: JObject) = new JsonListAssoc(o.obj)
implicit def pair2Assoc[A](t: (String, A))(implicit ev: A => JValue) = new JsonAssoc(t)
implicit def pair2Assoc[A <% JValue](t: (String, A)) = new JsonAssoc(t)
class JsonAssoc[A](left: (String, A))(implicit ev: A => JValue) {
def ~[B](right: (String, B))(implicit ev1: B => JValue) = {
class JsonAssoc[A <% JValue](left: (String, A)) {
def ~[B <% JValue](right: (String, B)) = {
val l: JValue = left._2
val r: JValue = right._2
JObject(JField(left._1, l) :: JField(right._1, r) :: Nil)
......@@ -95,15 +92,10 @@ trait JsonDSL extends Implicits {
val l: JValue = left._2
JObject(JField(left._1, l) :: right.obj)
}
def ~~[B](right: (String, B))(implicit ev: B => JValue) = this.~(right)
def ~~(right: JObject) = this.~(right)
}
class JsonListAssoc(left: List[JField]) {
def ~(right: (String, JValue)) = JObject(left ::: List(JField(right._1, right._2)))
def ~(right: JObject) = JObject(left ::: right.obj)
def ~~(right: (String, JValue)) = this.~(right)
def ~~(right: JObject) = this.~(right)
}
}
}
\ No newline at end of file
#!/bin/bash
exec benchmark/target/start
\ No newline at end of file
......@@ -3,7 +3,7 @@ package org.json4s.benchmark
import com.google.caliper.{ Runner => CaliperRunner}
object Runner {
def main(args: Array[String]): Unit = {
def main(args: Array[String]) {
CaliperRunner.main(classOf[Json4sBenchmark], args)
}
}
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ package benchmark
import java.util.Date
import com.fasterxml.jackson.databind.{JsonNode, DeserializationFeature, ObjectMapper}
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import java.util.concurrent.atomic.AtomicInteger
class Json4sBenchmark extends SimpleScalaBenchmark {
......@@ -39,10 +40,11 @@ class Json4sBenchmark extends SimpleScalaBenchmark {
private[this] val mapper = new ObjectMapper()
mapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, false)
mapper.registerModule(DefaultScalaModule)
override def setUp(): Unit = {
override def setUp() {
val c = counter.incrementAndGet()
project = Project("test"+c, new Date, Some(Language("Scala"+c, 2.75+c)), List(
Team("QA"+c, List(Employee("John Doe"+c, 5+c), Employee("Mike"+c, 3+c))),
......@@ -91,4 +93,4 @@ class Json4sBenchmark extends SimpleScalaBenchmark {
jackson.JsonMethods.compact(jackson.JsonMethods.render(projectJValue))
}
}
}
\ No newline at end of file
......@@ -16,4 +16,4 @@ trait SimpleScalaBenchmark extends SimpleBenchmark {
}
result
}
}
}
\ No newline at end of file
......@@ -6,4 +6,4 @@ import java.util.Date
case class Project(name: String, startDate: Date, lang: Option[Language], teams: List[Team])
case class Language(name: String, version: Double)
case class Team(role: String, members: List[Employee])
case class Employee(name: String, experience: Int)
case class Employee(name: String, experience: Int)
\ No newline at end of file
import xml.Group
import sbtbuildinfo.Plugin._
import com.typesafe.sbt.SbtStartScript
import Dependencies._
import build._
parallelExecution in Test := false
lazy val root = Project(
id = "json4s",
base = file("."),
settings = json4sSettings ++ noPublish
) aggregate(core, native, json4sExt, jacksonSupport, scalazExt, json4sTests, mongo, ast, scalap, examples, benchmark)
lazy val ast = Project(
id = "json4s-ast",
base = file("ast"),
settings = json4sSettings ++ buildInfoSettings ++ Seq(
sourceGenerators in Compile += buildInfo.taskValue,
buildInfoKeys := Seq[BuildInfoKey](name, organization, version, scalaVersion, sbtVersion),
buildInfoPackage := "org.json4s"
)
)
lazy val scalap = Project(
id = "json4s-scalap",
base = file("scalap"),
settings = json4sSettings
)
lazy val core = Project(
id = "json4s-core",
base = file("core"),
settings = json4sSettings ++ Seq(
libraryDependencies ++= Seq(paranamer) ++ scalaXml(scalaVersion.value),
initialCommands in (Test, console) := """
|import org.json4s._
|import reflect._
""".stripMargin
)
) dependsOn(ast % "compile;test->test", scalap)
lazy val native = Project(
id = "json4s-native",
base = file("native"),
settings = json4sSettings
) dependsOn(core % "compile;test->test")
lazy val json4sExt = Project(
id = "json4s-ext",
base = file("ext"),
settings = json4sSettings ++ Seq(libraryDependencies ++= jodaTime)
) dependsOn(native % "provided->compile;test->test")
lazy val jacksonSupport = Project(
id = "json4s-jackson",
base = file("jackson"),
settings = json4sSettings ++ Seq(libraryDependencies ++= jackson)
) dependsOn(core % "compile;test->test")
lazy val examples = Project(
id = "json4s-examples",
base = file("examples"),
settings = json4sSettings ++ SbtStartScript.startScriptForClassesSettings ++ noPublish
) dependsOn(
core % "compile;test->test",
native % "compile;test->test",
jacksonSupport % "compile;test->test",
json4sExt,
mongo)
lazy val scalazExt = Project(
id = "json4s-scalaz",
base = file("scalaz"),
settings = json4sSettings ++ Seq(libraryDependencies += scalaz_core)
) dependsOn(core % "compile;test->test", native % "provided->compile", jacksonSupport % "provided->compile")
lazy val mongo = Project(
id = "json4s-mongo",
base = file("mongo"),
settings = json4sSettings ++ Seq(
libraryDependencies ++= Seq(
"org.mongodb" % "mongo-java-driver" % "3.3.0"
)
)) dependsOn(core % "compile;test->test")
lazy val json4sTests = Project(
id = "json4s-tests",
base = file("tests"),
settings = json4sSettings ++ Seq(
libraryDependencies ++= (specs.value :+ mockito),
initialCommands in (Test, console) :=
"""
|import org.json4s._
|import reflect._
""".stripMargin
) ++ noPublish
) dependsOn(core, native, json4sExt, scalazExt, jacksonSupport, mongo)
lazy val benchmark = Project(
id = "json4s-benchmark",
base = file("benchmark"),
settings = json4sSettings ++ SbtStartScript.startScriptForClassesSettings ++ Seq(
cancelable := true,
libraryDependencies ++= Seq(
"com.google.code.java-allocation-instrumenter" % "java-allocation-instrumenter" % "3.0.1",
"com.google.caliper" % "caliper" % "0.5-rc1",
"com.google.code.gson" % "gson" % "2.8.0"
),
runner in Compile in run := {
val (tp, tmp, si, base, options, strategy, javaHomeDir, connectIn) =
(thisProject.value, taskTemporaryDirectory.value, scalaInstance.value, baseDirectory.value, javaOptions.value, outputStrategy.value, javaHome.value, connectInput.value)
new MyRunner(tp.id, ForkOptions(javaHome = javaHomeDir, connectInput = connectIn, outputStrategy = strategy,
runJVMOptions = options, workingDirectory = Some(base)) )
}
) ++ noPublish
) dependsOn(core, native, jacksonSupport, json4sExt, mongo)
#!/bin/bash
./sbt 'json4s-benchmark/stage'
exec ./bench
\ No newline at end of file
This diff is collapsed.
......@@ -18,7 +18,7 @@ digraph json {
ast [label="Json AST"]
dsl [label="Json DSL"]
ser [label="Serialized\nstring"]
doc [label="Document"]
doc [label="<<scala.text>>\nDocument"]
s [label="String"]
class [label="Case class"]
xml [label="XML"]
......
core/json.png

55.1 KiB | W: | H:

core/json.png

57.8 KiB | W: | H:

core/json.png
core/json.png
core/json.png
core/json.png
  • 2-up
  • Swipe
  • Onion skin
package org.json4s
import java.util.{TimeZone, Date}
import java.util.Date
/** Conversions between String and Date.
*/
trait DateFormat {
def parse(s: String): Option[Date]
def format(d: Date): String
def timezone: TimeZone
}
}
\ No newline at end of file
package org.json4s
import JsonAST._
import scala.language.dynamics
class DynamicJValue(val raw: JValue) extends Dynamic {
......
......@@ -12,13 +12,10 @@ package org.json4s
* renameFrom("animalname", "name")
* )
* </pre>
*
* The third optional parameter "includeLazyVal" determines if serializer will serialize/deserialize lazy val fields or not.
*/
case class FieldSerializer[A](
serializer: PartialFunction[(String, Any), Option[(String, Any)]] = Map(),
deserializer: PartialFunction[JField, JField] = Map(),
includeLazyVal: Boolean = false
deserializer: PartialFunction[JField, JField] = Map()
)(implicit val mf: Manifest[A])
object FieldSerializer {
......