diff options
author | Jakob Odersky <jakob@odersky.com> | 2018-03-07 14:07:25 -0800 |
---|---|---|
committer | Jakob Odersky <jakob@odersky.com> | 2019-06-10 23:22:15 +0200 |
commit | a43a10a12fd5653e6050c652024764416b71ab54 (patch) | |
tree | 19824c4e4eb31f849d51520d57a484e4f4ca0640 /js | |
parent | da8ed26cfed5e958eeb29a3444ff882a46090459 (diff) | |
download | spray-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.template | 39 | ||||
-rw-r--r-- | js/src/main/scala/spray/json/ProductFormats.scala | 80 |
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 + } +} |