Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross build for ScalaJS and Scala Native #251

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
sudo: required
dist: trusty
language: scala
scala:
- 2.10.7
- 2.11.12
- 2.12.4
- 2.13.0-M3

before_install:
- curl https://raw.githubusercontent.com/scala-native/scala-native/9069e8d447f7a9a5439bffbb6a706b5cc70bd631/bin/travis_setup.sh | bash -x

script:
- sbt ++$TRAVIS_SCALA_VERSION test mimaReportBinaryIssues
- sbt +test +mimaReportBinaryIssues
jdk:
- oraclejdk8
notifications:
email:
- [email protected]
- [email protected]
28 changes: 28 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
Version 2.0.0 UNRELEASED (2018-03-07)
-------------------------------------

This version mainly updates the build and introduces support for
cross-compiling spray to ScalaJS and Scala Native, in addition to
traditional Scala on the JVM.

Source compatibility with 1.x releases is mostly maintained for the
JVM project, although there are a couple of internal changes that may
leak:

- Methods that require Java reflection have been moved out of
`ProductFormats` into `ReflectiveProductFormats` and are only
available on the JVM version.

- The mixins of `DefaultJsonProtocol` have been mostly grouped into a
new trait `SharedJsonProtocol` which contains all
platform-independent formats (i.e. all formats but reflective
ones). `DefaultJsonProtocol` extends `SharedJsonProtocol` with
`ReflectiveProductFormats` on the JVM.

ScalaJS and Scala Native versions do not implement reflective product
formats, meaning that there are no more `jsonFormatX()` methods. The
overloaded method `jsonFormat(<constructor>, <field_names>*)` is still
available and may be used as a workaround.

Support for Scala 2.10 has been dropped.

Version 1.3.3 (2016-12-29)
--------------------------

Expand Down
10 changes: 9 additions & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ It supports the following features:
* Type-class based (de)serialization of custom objects (no reflection, no intrusion)
* No external dependencies

It is available for Scala on the JVM, ScalaJS and Scala Native<sup>1</sup>.

_spray-json_ allows you to convert between
* String JSON documents
* JSON Abstract Syntax Trees (ASTs) with base type JsValue
Expand All @@ -17,6 +19,9 @@ as depicted in this diagram:

![Spray-JSON conversions](images/Conversions.png "Conversions possible with Spray-JSON")

<sup>1</sup>: *The versions for ScalaJS and Scala Native currently do not support generating
case class formats through reflection.*

### Installation

_spray-json_ is available from maven central.
Expand All @@ -26,7 +31,7 @@ Latest release: [![Maven Central](https://maven-badges.herokuapp.com/maven-centr
If you use SBT you can include _spray-json_ in your project with

```scala
libraryDependencies += "io.spray" %% "spray-json" % "1.3.3"
libraryDependencies += "io.spray" %% "spray-json" % "<latest_version>"
```

### Usage
Expand Down Expand Up @@ -131,6 +136,9 @@ method). The `jsonFormatX` methods try to extract the field names of your case c
field names or if your JSON objects use member names that differ from the case class fields you can also use
`jsonFormat` directly.

*Note that spray-json for ScalaJS or Scala Native does not support the `jsonFormatX` methods,
and hence using the `jsonFormat` overloads is required on these platforms.*

There is one additional quirk: If you explicitly declare the companion object for your case class the notation above will
stop working. You'll have to explicitly refer to the companion objects `apply` method to fix this:

Expand Down
184 changes: 79 additions & 105 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,109 +1,83 @@
// shadow sbt-scalajs' crossProject and CrossType until Scala.js 1.0.0 is released
import sbtcrossproject.{crossProject, CrossType}
import com.typesafe.tools.mima.core.{ProblemFilters, ReversedMissingMethodProblem}

name := "spray-json"

version := "1.3.4"

organization := "io.spray"

organizationHomepage := Some(new URL("http://spray.io"))

description := "A Scala library for easy and idiomatic JSON (de)serialization"

homepage := Some(new URL("https://github.com/spray/spray-json"))

startYear := Some(2011)

licenses := Seq("Apache 2" -> new URL("http://www.apache.org/licenses/LICENSE-2.0.txt"))

scalaVersion := "2.11.12"

scalacOptions ++= Seq("-feature", "-language:_", "-unchecked", "-deprecation", "-Xlint", "-encoding", "utf8")

resolvers += Opts.resolver.sonatypeReleases

libraryDependencies ++=
(CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, n)) if n >= 13 =>
Seq("org.scala-lang.modules" %% "scala-parallel-collections" % "0.1.2")
case _ =>
Nil
})

libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 10)) => Seq(
"org.specs2" %% "specs2-core" % "3.8.9" % "test",
"org.specs2" %% "specs2-scalacheck" % "3.8.9" % "test",
"org.scalacheck" %% "scalacheck" % "1.13.4" % "test"
)
case Some((2, n)) if n >= 11 => Seq(
"org.specs2" %% "specs2-core" % "4.0.2" % "test",
"org.specs2" %% "specs2-scalacheck" % "4.0.2" % "test",
"org.scalacheck" %% "scalacheck" % "1.13.5" % "test"
)
case _ => Nil
})

(scalacOptions in doc) ++= Seq("-doc-title", name.value + " " + version.value)

// generate boilerplate
Boilerplate.settings

// OSGi settings
osgiSettings

OsgiKeys.exportPackage := Seq("""spray.json.*;version="${Bundle-Version}"""")

OsgiKeys.importPackage := Seq("""scala.*;version="$<range;[==,=+);%s>"""".format(scalaVersion.value))

OsgiKeys.importPackage ++= Seq("""spray.json;version="${Bundle-Version}"""", "*")

OsgiKeys.additionalHeaders := Map("-removeheaders" -> "Include-Resource,Private-Package")

// Migration Manager
mimaPreviousArtifacts := (CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 13)) => Set.empty
case _ => Set("io.spray" %% "spray-json" % "1.3.3")
})

mimaBinaryIssueFilters := Seq(
ProblemFilters.exclude[ReversedMissingMethodProblem]("spray.json.PrettyPrinter.organiseMembers")
)

///////////////
// publishing
///////////////

crossScalaVersions := Seq("2.10.7", "2.11.12", "2.12.4", "2.13.0-M3")

scalaBinaryVersion := {
val sV = scalaVersion.value
if (CrossVersion.isScalaApiCompatible(sV))
CrossVersion.binaryScalaVersion(sV)
else
sV
}

publishMavenStyle := true

useGpg := true

publishTo := {
val nexus = "https://oss.sonatype.org/"
if (version.value.trim.endsWith("SNAPSHOT"))
Some("snapshots" at nexus + "content/repositories/snapshots")
else
Some("releases" at nexus + "service/local/staging/deploy/maven2")
}

pomIncludeRepository := { _ => false }

pomExtra :=
<scm>
<url>git://github.com/spray/spray.git</url>
<connection>scm:git:[email protected]:spray/spray.git</connection>
</scm>
<developers>
<developer><id>sirthias</id><name>Mathias Doenitz</name></developer>
<developer><id>jrudolph</id><name>Johannes Rudolph</name></developer>
</developers>
lazy val sprayJson =
crossProject(JVMPlatform, JSPlatform, NativePlatform)
.crossType(CrossType.Full)
.in(file("."))
.settings(
name := "spray-json",
version := "2.0.0-SNAPSHOT",
scalaVersion := crossScalaVersions.value.head,
scalacOptions ++= Seq("-feature", "-language:_", "-unchecked", "-deprecation", "-Xlint", "-encoding", "utf8"),
(scalacOptions in doc) ++= Seq("-doc-title", name.value + " " + version.value),
libraryDependencies ++=
(CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, n)) if n >= 13 =>
Seq("org.scala-lang.modules" %%% "scala-parallel-collections" % "0.1.2")
case _ =>
Nil
}),
scalaBinaryVersion := {
val sV = scalaVersion.value
if (CrossVersion.isScalaApiCompatible(sV))
CrossVersion.binaryScalaVersion(sV)
else
sV
},
// Workaround for "Shared resource directory is ignored"
// https://github.com/portable-scala/sbt-crossproject/issues/74
unmanagedResourceDirectories in Test += (baseDirectory in ThisBuild).value / "shared/src/test/resources"
)
.enablePlugins(spray.boilerplate.BoilerplatePlugin)
.configurePlatforms(JVMPlatform)(_.enablePlugins(SbtOsgi))
.platformsSettings(JVMPlatform, JSPlatform)(
libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 10)) => Seq(
"org.specs2" %%% "specs2-core" % "4.0.2" % "test",
"org.specs2" %%% "specs2-scalacheck" % "4.0.2" % "test",
"org.scalacheck" %%% "scalacheck" % "1.13.4" % "test"
)
case Some((2, n)) if n >= 11 => Seq(
"org.specs2" %%% "specs2-core" % "4.0.2" % "test",
"org.specs2" %%% "specs2-scalacheck" % "4.0.2" % "test",
"org.scalacheck" %%% "scalacheck" % "1.13.5" % "test"
)
case _ => Nil
}),
unmanagedSourceDirectories in Test += (baseDirectory in ThisBuild).value / "shared/src/test/scala-jvm-js"
)
.jvmSettings(
crossScalaVersions := Seq("2.13.0-M3", "2.12.4", "2.11.12"),
OsgiKeys.exportPackage := Seq("""spray.json.*;version="${Bundle-Version}""""),
OsgiKeys.importPackage := Seq("""scala.*;version="$<range;[==,=+);%s>"""".format(scalaVersion.value)),
OsgiKeys.importPackage ++= Seq("""spray.json;version="${Bundle-Version}"""", "*"),
OsgiKeys.additionalHeaders := Map("-removeheaders" -> "Include-Resource,Private-Package"),
mimaPreviousArtifacts := (CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 13)) => Set.empty
case _ => Set.empty //Set("io.spray" %% "spray-json" % "1.3.3")
}),
mimaBinaryIssueFilters := Seq(
ProblemFilters.exclude[ReversedMissingMethodProblem]("spray.json.PrettyPrinter.organiseMembers")
)
)
.jsSettings(
crossScalaVersions := Seq("2.12.4", "2.11.12"),
)
.nativeSettings(
crossScalaVersions := Seq("2.11.12")
)

lazy val sprayJsonJVM = sprayJson.jvm
lazy val sprayJsonJS = sprayJson.js
lazy val sprayJsonNative = sprayJson.native

lazy val root = (project in file("."))
.aggregate(sprayJsonJVM, sprayJsonJS, sprayJsonNative)
.settings(
publish := {},
publishLocal := {}
)
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,8 @@ package spray.json

/**
* Provides all the predefined JsonFormats.
*/
*/
trait DefaultJsonProtocol
extends BasicFormats
with StandardFormats
with CollectionFormats
with ProductFormats
with AdditionalFormats
extends SharedJsonProtocol

object DefaultJsonProtocol extends DefaultJsonProtocol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2011,2012 Mathias Doenitz, Johannes Rudolph
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package spray.json

import scala.reflect.ClassTag
import scala.reflect.classTag

trait ReflectiveProductFormatsInstances { self: ReflectiveProductFormats with StandardFormats =>
[# // Case classes with 1 parameters

def jsonFormat1[[#P1 :JF#], T <: Product :ClassTag](construct: ([#P1#]) => T): RootJsonFormat[T] = {
val Array([#p1#]) = extractFieldNames(classTag[T])
jsonFormat(construct, [#p1#])
}#


]
}
27 changes: 27 additions & 0 deletions jvm/src/main/scala/spray/json/DefaultJsonProtocol.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Original implementation (C) 2009-2011 Debasish Ghosh
* Adapted and extended in 2011 by Mathias Doenitz
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package spray.json

/**
* Provides all the predefined JsonFormats.
*/
trait DefaultJsonProtocol
extends SharedJsonProtocol
with ReflectiveProductFormats

object DefaultJsonProtocol extends DefaultJsonProtocol
Loading