summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorJakob Odersky <jakob@odersky.com>2018-03-07 14:07:25 -0800
committerJakob Odersky <jakob@odersky.com>2019-06-10 23:22:15 +0200
commita43a10a12fd5653e6050c652024764416b71ab54 (patch)
tree19824c4e4eb31f849d51520d57a484e4f4ca0640 /js
parentda8ed26cfed5e958eeb29a3444ff882a46090459 (diff)
downloadspray-json-a43a10a12fd5653e6050c652024764416b71ab54.tar.gz
spray-json-a43a10a12fd5653e6050c652024764416b71ab54.tar.bz2
spray-json-a43a10a12fd5653e6050c652024764416b71ab54.zip
Add support for ScalaJS and Scala Native
Binary compatibility with previous versions is maintained.
Diffstat (limited to 'js')
-rw-r--r--js/src/main/boilerplate/spray/json/ProductFormatsInstances.scala.template39
-rw-r--r--js/src/main/scala/spray/json/ProductFormats.scala80
2 files changed, 119 insertions, 0 deletions
diff --git a/js/src/main/boilerplate/spray/json/ProductFormatsInstances.scala.template b/js/src/main/boilerplate/spray/json/ProductFormatsInstances.scala.template
new file mode 100644
index 0000000..d6f83f7
--- /dev/null
+++ b/js/src/main/boilerplate/spray/json/ProductFormatsInstances.scala.template
@@ -0,0 +1,39 @@
+/*
+ * 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
+
+trait ProductFormatsInstances { self: ProductFormats with StandardFormats =>
+[# // Case classes with 1 parameters
+
+ def jsonFormat[[#P1 :JF#], T <: Product](construct: ([#P1#]) => T, [#fieldName1: String#]): RootJsonFormat[T] = new RootJsonFormat[T]{
+ def write(p: T) = {
+ val fields = new collection.mutable.ListBuffer[(String, JsValue)]
+ fields.sizeHint(1 * 2)
+ [#fields ++= productElement##2Field[P1](fieldName1, p, 0)#
+ ]
+ JsObject(fields: _*)
+ }
+ def read(value: JsValue) = {
+ [#val p1V = fromField[P1](value, fieldName1)#
+ ]
+ construct([#p1V#])
+ }
+ }#
+
+
+]
+}
diff --git a/js/src/main/scala/spray/json/ProductFormats.scala b/js/src/main/scala/spray/json/ProductFormats.scala
new file mode 100644
index 0000000..bc06eac
--- /dev/null
+++ b/js/src/main/scala/spray/json/ProductFormats.scala
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 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 the helpers for constructing custom JsonFormat implementations for types implementing the Product trait
+ * (especially case classes)
+ */
+trait ProductFormats extends ProductFormatsInstances {
+ this: StandardFormats =>
+
+ def jsonFormat0[T](construct: () => T): RootJsonFormat[T] =
+ new RootJsonFormat[T] {
+ def write(p: T) = JsObject()
+ def read(value: JsValue) = value match {
+ case JsObject(_) => construct()
+ case _ => throw new DeserializationException("Object expected")
+ }
+ }
+
+ // helpers
+
+ protected def productElement2Field[T](fieldName: String, p: Product, ix: Int, rest: List[JsField] = Nil)
+ (implicit writer: JsonWriter[T]): List[JsField] = {
+ val value = p.productElement(ix).asInstanceOf[T]
+ writer match {
+ case _: OptionFormat[_] if (value == None) => rest
+ case _ => (fieldName, writer.write(value)) :: rest
+ }
+ }
+
+ protected def fromField[T](value: JsValue, fieldName: String)
+ (implicit reader: JsonReader[T]) = value match {
+ case x: JsObject if
+ (reader.isInstanceOf[OptionFormat[_]] &
+ !x.fields.contains(fieldName)) =>
+ None.asInstanceOf[T]
+ case x: JsObject =>
+ try reader.read(x.fields(fieldName))
+ catch {
+ case e: NoSuchElementException =>
+ deserializationError("Object is missing required member '" + fieldName + "'", e, fieldName :: Nil)
+ case DeserializationException(msg, cause, fieldNames) =>
+ deserializationError(msg, cause, fieldName :: fieldNames)
+ }
+ case _ => deserializationError("Object expected in field '" + fieldName + "'", fieldNames = fieldName :: Nil)
+ }
+
+}
+
+/**
+ * This trait supplies an alternative rendering mode for optional case class members.
+ * Normally optional members that are undefined (`None`) are not rendered at all.
+ * By mixing in this trait into your custom JsonProtocol you can enforce the rendering of undefined members as `null`.
+ * (Note that this only affect JSON writing, spray-json will always read missing optional members as well as `null`
+ * optional members as `None`.)
+ */
+trait NullOptions extends ProductFormats {
+ this: StandardFormats =>
+
+ override protected def productElement2Field[T](fieldName: String, p: Product, ix: Int, rest: List[JsField])
+ (implicit writer: JsonWriter[T]) = {
+ val value = p.productElement(ix).asInstanceOf[T]
+ (fieldName, writer.write(value)) :: rest
+ }
+}