Skip to content

Commit

Permalink
merging from master
Browse files Browse the repository at this point in the history
  • Loading branch information
bathalh committed Nov 1, 2017
2 parents f6464a0 + 82b422f commit edd2ac2
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 56 deletions.
62 changes: 14 additions & 48 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ as depicted in this diagram:
### Installation

_spray-json_ is available from maven central.

Latest release: [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.spray/spray-json_2.12/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.spray/spray-json_2.12)
The latest release is `1.3.3` and is built against Scala 2.10.x, 2.11.x, and 2.12.x.

If you use SBT you can include _spray-json_ in your project with

Expand All @@ -42,25 +41,26 @@ import DefaultJsonProtocol._ // if you don't supply your own Protocol (see below
and do one or more of the following:

* Parse a JSON string into its Abstract Syntax Tree (AST) representation

```scala
val source = """{ "some": "JSON source" }"""
val jsonAst = source.parseJson // or JsonParser(source)
```

* Print a JSON AST back to a String using either the `CompactPrinter` or the `PrettyPrinter`

```scala
val json = jsonAst.prettyPrint // or .compactPrint
```

* Convert any Scala object to a JSON AST using the `toJson` extension method
* Convert any Scala object to a JSON AST using the pimped `toJson` method

```scala
val jsonAst = List(1, 2, 3).toJson
```

* Convert a JSON AST to a Scala object with the `convertTo` method

```scala
val myObject = jsonAst.convertTo[MyObjectType]
```
Expand Down Expand Up @@ -243,38 +243,6 @@ object MyJsonProtocol extends DefaultJsonProtocol {
This is a bit more verbose in its definition and the resulting JSON but transports the field semantics over to the
JSON side. Note that this is the approach _spray-json_ uses for case classes.

### Providing JsonFormats for unboxed types

A value class

```scala
case class PhoneNumber(value: String) extends AnyVal
val num = PhoneNumber("+1 212 555 1111")
```

or a class with multiple members

```scala
case class Money(currency: String, amount: BigDecimal)
val bal = Money("USD", 100)
```

can be handled as above with `jsonFormatX`, etc.
It may be preferable, however, to serialize such instances without object boxing:
as `"USD 100"` instead of `{"currency":"USD","amount":100}`.
This requires explicit (de)serialization logic:

```scala
implicit object MoneyFormat extends JsonFormat[Money] {
val fmt = """([A-Z]{3}) ([0-9.]+)""".r
def write(m: Money) = JsString(s"${m.currency} ${m.amount}")
def read(json: JsValue) = json match {
case JsString(fmt(c, a)) => Money(c, BigDecimal(a))
case _ => deserializationError("String expected")
}
}
```


### JsonFormat vs. RootJsonFormat

Expand Down Expand Up @@ -329,22 +297,20 @@ _spray-json_ is licensed under [APL 2.0].

### Mailing list

Spray-json is in primarily "maintanance mode", as it contains the basic functionality it is meant to deliver.
If you have any questions about it though, please open issues on this repository.

Please use the [spray-user] mailing list if you have any questions.

### Maintanance mode

_spray-json_ is largely considered feature-complete for the basic functionality it provides.
It is currently maintained by the Akka team at Lightbend.
### Patch Policy

Feedback and contributions to the project, no matter what kind, are always very welcome.

However, patches can only be accepted from their original author.
Along with any patches, please state that the patch is your original work and that you license the work to the
_spray-json_ project under the project’s open source license.


[JSON]: http://json.org
[repo.spray.io]: http://repo.spray.io
[SJSON]: https://github.com/debasishg/sjson
[Databinder-Dispatch]: https://github.com/dispatch/classic
[Databinder-Dispatch]: https://github.com/n8han/Databinder-Dispatch
[APL 2.0]: http://www.apache.org/licenses/LICENSE-2.0
[spray-user]: http://groups.google.com/group/spray-user
5 changes: 2 additions & 3 deletions src/main/scala/spray/json/JsValue.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2009-2011 Mathias Doenitz
* Inspired by a similar implementation by Nathan Hamblen
* (https://github.com/dispatch/classic)
* (https://github.com/n8han/Databinder-Dispatch)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -28,7 +28,6 @@ sealed abstract class JsValue {
def toString(printer: (JsValue => String)) = printer(this)
def compactPrint = CompactPrinter(this)
def prettyPrint = PrettyPrinter(this)
def sortedPrint = SortedPrinter(this)
def convertTo[T :JsonReader]: T = jsonReader[T].read(this)

/**
Expand Down Expand Up @@ -124,5 +123,5 @@ case object JsFalse extends JsBoolean {
*/
case object JsNull extends JsValue

/** The representation for JSON missing value. **/
/** The representation for JSON undefined. **/
case object JsUndefined extends JsValue
2 changes: 2 additions & 0 deletions src/main/scala/spray/json/JsonParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class JsonParser(input: ParserInput) {
(cursorChar: @switch) match {
case 'f' => simpleValue(`false`(), JsFalse)
case 'n' => simpleValue(`null`(), JsNull)
case 'u' => simpleValue(`undefined`(), JsUndefined)
case 't' => simpleValue(`true`(), JsTrue)
case '{' => advance(); `object`()
case '[' => advance(); `array`()
Expand All @@ -71,6 +72,7 @@ class JsonParser(input: ParserInput) {

private def `false`() = advance() && ch('a') && ch('l') && ch('s') && ws('e')
private def `null`() = advance() && ch('u') && ch('l') && ws('l')
private def `undefined`() = advance() && ch('n') && ch('d') && ch('e') && ch('f') && ch('i') && ch('n') && ch('e') && ws('d')
private def `true`() = advance() && ch('r') && ch('u') && ws('e')

// http://tools.ietf.org/html/rfc4627#section-2.2
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/spray/json/JsonPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ trait JsonPrinter extends (JsValue => String) {
protected def printLeaf(x: JsValue, sb: JStringBuilder) {
x match {
case JsNull => sb.append("null")
case JsUndefined => sb.append("undefined")
case JsTrue => sb.append("true")
case JsFalse => sb.append("false")
case JsNumber(x) => sb.append(x)
Expand Down
4 changes: 2 additions & 2 deletions src/test/scala/spray/json/CompactPrinterSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ class CompactPrinterSpec extends Specification {
mustEqual "{}"
)
"properly print a simple JsArray" in (
CompactPrinter(JsArray(JsNull, JsNumber(1.23), JsObject("key" -> JsBoolean(true))))
mustEqual """[null,1.23,{"key":true}]"""
CompactPrinter(JsArray(JsNull, JsUndefined, JsNumber(1.23), JsObject("key" -> JsBoolean(true))))
mustEqual """[null,undefined,1.23,{"key":true}]"""
)
"properly print a JSON padding (JSONP) if requested" in {
CompactPrinter(JsTrue, Some("customCallback")) mustEqual("customCallback(true)")
Expand Down
7 changes: 5 additions & 2 deletions src/test/scala/spray/json/JsonParserSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ class JsonParserSpec extends Specification {
"parse 'null' to JsNull" in {
JsonParser("null") === JsNull
}
"parse 'undefined' to JsUndefined" in {
JsonParser("undefined") === JsUndefined
}
"parse 'true' to JsTrue" in {
JsonParser("true") === JsTrue
}
Expand Down Expand Up @@ -57,8 +60,8 @@ class JsonParserSpec extends Specification {
JsObject("key" -> JsNumber(42), "key2" -> JsString("value"))
)
"parse a simple JsArray" in (
JsonParser("""[null, 1.23 ,{"key":true } ] """) ===
JsArray(JsNull, JsNumber(1.23), JsObject("key" -> JsTrue))
JsonParser("""[null, undefined, 1.23 ,{"key":true } ] """) ===
JsArray(JsNull, JsUndefined, JsNumber(1.23), JsObject("key" -> JsTrue))
)
"parse directly from UTF-8 encoded bytes" in {
val json = JsObject(
Expand Down
2 changes: 1 addition & 1 deletion src/test/scala/spray/json/ProductFormatsSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class ProductFormatsSpec extends Specification {
JsObject("b" -> JsNumber(4.2)).convertTo[Test2] must
throwA(new DeserializationException("Object is missing required member 'a'"))
)
"not require the presence of Option fields for deserialization" in {
"not require the presence of optional fields for deserialization" in {
JsObject("a" -> JsNumber(42)).convertTo[Test2] mustEqual Test2(42, None)
}
"not require the presence of Tription fields for deserialization" in {
Expand Down

0 comments on commit edd2ac2

Please sign in to comment.