Skip to content

Commit 19c0ef6

Browse files
committed
Version 0.7.0
2 parents 2e43a62 + 03440c6 commit 19c0ef6

File tree

16 files changed

+280
-99
lines changed

16 files changed

+280
-99
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Version history
2+
3+
## 0.7.0
4+
5+
* Removed deprecated builder objects `obj` and `arr`
6+
* Added `toJObject` and `toJArray` methods
7+
* Fixed `null` rendering to arrays and objects
8+
* Throw an exception if trying to render `JUndefined`

README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Zeison
22

33
[![Build Status](https://travis-ci.org/milankinen/zeison.svg?branch=master)](https://travis-ci.org/milankinen/zeison)
4+
[![codecov.io](http://codecov.io/github/milankinen/zeison/coverage.svg?branch=master)](http://codecov.io/github/milankinen/zeison?branch=master)
45

56
Small, fast and easy-to-use JSON library for Scala.
67

@@ -23,7 +24,7 @@ Zeison is extremely lightweight - binaries (including jawn-parser) require under
2324

2425
To use Zeison in you project, add the following line to your `build.sbt`
2526

26-
libraryDependencies += "org.tsers.zeison" %% "zeison" % "0.6.0"
27+
libraryDependencies += "org.tsers.zeison" %% "zeison" % "0.7.0"
2728

2829
All methods and types are inside object `org.tsers.zeison.Zeison` so in order to
2930
use them in your code, you must add the following import
@@ -103,6 +104,9 @@ val obj = Zeison.toJson(Map(
103104
"meta" -> data.meta,
104105
"primes" -> Seq(1,2,3,5)
105106
))
107+
// or shortcuts for objects and arrays
108+
val justObj = Zeison.toJObject("foo" -> "bar", "tsers" -> 1)
109+
val justArr = Zeison.toJArray(1, 2, 3, "tsers", obj)
106110

107111
// immutable field adding
108112
// .copy(..) works for JSON objects - other types cause runtime exception
@@ -156,3 +160,16 @@ assert(Zeison.render(custom) == s"""{"createdAt":"${toISO8601(now)}"}""")
156160
assert(custom.createdAt.is[Date])
157161
assert(custom.createdAt.to[Date] == now)
158162
```
163+
164+
## License
165+
166+
MIT
167+
168+
169+
## Contributing
170+
171+
Please feel free to leave a pull request to `development` branch. Before leaving
172+
the pull request, please check that tests are passed by using script
173+
174+
./scripts/test
175+

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import SonatypeKeys._
33
sonatypeSettings
44

55
name := "Zeison"
6-
version := "0.6.0"
6+
version := "0.7.0"
77
profileName := "org.tsers"
88
organization := "org.tsers.zeison"
99
scalaVersion := "2.10.5"

project/plugins.sbt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")
2-
31
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "0.2.1")
42

53
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.1.0")

scripts/release

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env bash
2+
3+
echo "Release new version to Maven"
4+
./sbt clean +compile +publishSigned
5+
./sbt sonatypeRelease
6+
echo "Done"

scripts/test

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env bash
2+
3+
echo "Run unit tests and create coverage report"
4+
./sbt clean coverage +test coverageReport

src/main/scala/org/tsers/zeison/Rendering.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ private [zeison] object Rendering {
117117
}
118118

119119
value match {
120-
case JUndefined => new ZeisonException("Can't render JUndefined")
120+
case JUndefined => throw new ZeisonException("Can't render JUndefined")
121121
case JNull => sb.append("null")
122122
case JBoolean(v) => sb.append(v)
123123
case num: JNum => sb.append(num.valueAsString)

src/main/scala/org/tsers/zeison/Zeison.scala

Lines changed: 22 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -42,31 +42,9 @@ object Zeison {
4242

4343
def toJson(any: Any): JValue = toJValue(any)
4444

45-
@deprecated
46-
def from(any: Any): JValue = {
47-
toJValue(any)
48-
}
49-
50-
@deprecated
51-
object obj {
52-
def empty = JObject(Map.empty)
53-
54-
def apply(fields: (String, Any)*): JObject = {
55-
val fieldMap = new util.LinkedHashMap[String, JValue](fields.size)
56-
fields.foreach { case (key, value) => toJValue(value).toOption.foreach(jVal => fieldMap.put(key, jVal)) }
57-
JObject(new FieldMap(fieldMap))
58-
}
59-
}
60-
61-
@deprecated
62-
object arr {
63-
def empty = JArray(Vector.empty)
64-
65-
def apply(elems: Any*): JArray = {
66-
Zeison.from(elems.toIterable).asInstanceOf[JArray]
67-
}
68-
}
45+
def toJObject(fields: (String, Any)*): JObject = toJValue(fields.toMap).asInstanceOf[JObject]
6946

47+
def toJArray(elems: Any*): JArray = toJValue(elems).asInstanceOf[JArray]
7048

7149
/*
7250
* JSON rendering
@@ -87,11 +65,20 @@ object Zeison {
8765
// ATTENTION: this must be overridden because otherwise traversable trait
8866
// will cause StackOverflowError
8967
override def toString() = {
90-
def className = getClass.getSimpleName
68+
def str(value: Any) = s"${getClass.getSimpleName}($value)"
69+
def extractNum(num: JNum): Any = {
70+
if (num.hasDecimals) num.valueAsDouble else num.valueAsLong
71+
}
72+
9173
this match {
92-
case JNull => "JNull"
93-
case JUndefined => "JUndefined"
94-
case jValue => className + "(" + valueOf(jValue).getOrElse("<invalid>") + ")"
74+
case JNull => "JNull"
75+
case JUndefined => "JUndefined"
76+
case num: JNum => str(extractNum(num))
77+
case JBoolean(value) => str(value)
78+
case JString(value) => str(value)
79+
case JObject(value) => str(value)
80+
case JArray(value) => str(value)
81+
case custom: JCustom => str(custom.value)
9582
}
9683
}
9784

@@ -284,7 +271,7 @@ object Zeison {
284271

285272
override def -(key: String): Map[String, JValue] = {
286273
val copied = new util.LinkedHashMap[String, JValue](fields)
287-
fields.remove(key)
274+
copied.remove(key)
288275
new FieldMap(copied)
289276
}
290277
}
@@ -355,33 +342,19 @@ object Zeison {
355342
case value: Float => JDouble(value)
356343
case value: Double => JDouble(value)
357344
case value: BigDecimal => JDouble(value.toDouble)
358-
case value: java.lang.Float => JDouble(Float.unbox(value))
359-
case value: java.lang.Double => JDouble(Double.unbox(value))
360345
case value: Number => JInt(value.longValue())
361346
case value: Char => JString(value.toString)
362347
case value: String => JString(value)
363-
case f: scala.collection.Map[_,_] => JObject(f.flatMap { case (k, v) => toJValue(v).toOption.map((k.toString, _)) }.toMap)
364-
case elems: col.TraversableOnce[_] => JArray(elems.flatMap(e => toJValue(e).toOption).toVector)
365-
case elems: Array[_] => JArray(elems.flatMap(e => toJValue(e).toOption).toVector)
348+
case f: scala.collection.Map[_,_] => JObject(f.flatMap { case (k, v) => toOption(toJValue(v)).map((k.toString, _)) }.toMap)
349+
case elems: col.TraversableOnce[_] => JArray(elems.flatMap(e => toOption(toJValue(e))).toVector)
350+
case elems: Array[_] => JArray(elems.flatMap(e => toOption(toJValue(e))).toVector)
366351
case value => throw new ZeisonException(s"Can't parse value ($value) to JValue")
367352
}
368353
}
369354

370-
def valueOf(jValue: JValue): Option[Any] = {
371-
def extractNum(num: JNum): Any = {
372-
if (num.hasDecimals) num.valueAsDouble else num.valueAsLong
373-
}
374-
375-
jValue match {
376-
case JUndefined => None
377-
case JNull => Some(null)
378-
case JBoolean(value) => Some(value)
379-
case num: JNum => Some(extractNum(num))
380-
case JString(value) => Some(value)
381-
case JObject(value) => Some(value)
382-
case JArray(value) => Some(value)
383-
case custom: JCustom => Some(custom.value)
384-
}
355+
def toOption(jValue: JValue): Option[JValue] = {
356+
if (jValue.isDefined) Some(jValue) else None
385357
}
358+
386359
}
387360
}

src/test/scala/org/tsers/zeison/ConversionsSpec.scala

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package org.tsers.zeison
22

3+
import java.util.Date
4+
5+
import org.tsers.zeison.Zeison.JCustom
6+
37
class ConversionsSpec extends BaseSpec {
48
import Zeison._
59

@@ -21,18 +25,33 @@ class ConversionsSpec extends BaseSpec {
2125
it("supports integers") {
2226
json.int should be('int)
2327
json.int.toInt should equal(123)
28+
json.int.toLong should equal(123L)
2429
json.bool should not be 'int
2530
intercept[ZeisonException] {
2631
json.bool.toInt
2732
}
33+
intercept[ZeisonException] {
34+
json.dbl.toInt
35+
}
36+
intercept[ZeisonException] {
37+
json.dbl.toLong
38+
}
39+
intercept[ZeisonException] {
40+
JDouble(1.2).toInt
41+
}
42+
intercept[ZeisonException] {
43+
JDouble(1.2).toLong
44+
}
2845
}
2946

3047
it("supports doubles") {
3148
json.dbl should be('double)
3249
json.dbl.toDouble should equal(123.3)
50+
json.int.toDouble should equal(123.0)
51+
JInt(1).toDouble should equal(1.0)
3352
json.bool should not be 'double
3453
intercept[ZeisonException] {
35-
json.int.toBool
54+
json.str.toDouble
3655
}
3756
}
3857

@@ -74,6 +93,9 @@ class ConversionsSpec extends BaseSpec {
7493
describe("JSON conversions") {
7594
it("support object casting to map") {
7695
json.obj.toMap.mapValues(_.toInt) should equal(Map("foo" -> 1, "bar" -> 2))
96+
intercept[ZeisonException] {
97+
json.int.toMap
98+
}
7799
}
78100

79101
it("support array casting to seq") {
@@ -93,4 +115,37 @@ class ConversionsSpec extends BaseSpec {
93115
}
94116
}
95117

118+
describe("custom types") {
119+
it("can be used to contruct Zeison objects") {
120+
val obj = toJObject("custom" -> JTsers(Tsers("foo")))
121+
render(obj) should equal("""{"custom":{"tsers" : "foo"}}""")
122+
}
123+
124+
it("can be extracted from Zeison objects") {
125+
val obj = toJObject("custom" -> JTsers(Tsers("foo")))
126+
obj.custom.is[Tsers] should be(true)
127+
obj.custom.to[Tsers] should equal(Tsers("foo"))
128+
}
129+
130+
it("can't be cast to other objects") {
131+
val obj = toJObject("custom" -> JTsers(Tsers("foo")))
132+
obj.custom.is[Date] should be(false)
133+
intercept[ZeisonException] {
134+
obj.custom.to[Date]
135+
}
136+
}
137+
138+
it("can't be extracted from native Zeison objects") {
139+
intercept[ZeisonException] {
140+
json.str.to[Tsers]
141+
}
142+
}
143+
}
144+
96145
}
146+
147+
case class JTsers(override val value: Tsers) extends JCustom {
148+
override def valueAsJson: String = s"""{"tsers" : "${value.msg}"}"""
149+
}
150+
151+
case class Tsers(msg: Any)

src/test/scala/org/tsers/zeison/CustomTypesSpec.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ class CustomTypesSpec extends BaseSpec {
2121
describe("Custom types") {
2222

2323
it("can be be added to built JSON object and rendered correctly") {
24-
val json = obj("date" -> JDate(parseDate("2011-11-11 11:11")))
24+
val json = toJson(Map("date" -> JDate(parseDate("2011-11-11 11:11"))))
2525
render(json) should equal("""{"date":"2011-11-11T11:11:00"}""")
2626
}
2727

2828
it("can be tested from the built JSON") {
2929
val date = JDate(parseDate("2011-11-11 11:11"))
30-
val json = obj("date" -> date, "num" -> 2)
30+
val json = toJson(Map("date" -> date, "num" -> 2))
3131

3232
json.date.isInt should equal(false)
3333
json.date.is[Date] should equal(true)
@@ -37,13 +37,13 @@ class CustomTypesSpec extends BaseSpec {
3737

3838
it("can be extracted from the built JSON") {
3939
val date = JDate(parseDate("2011-11-11 11:11"))
40-
val json = obj("date" -> date)
40+
val json = toJson(Map("date" -> date))
4141

4242
json.date.to[Date] should equal(date.value)
4343
}
4444

4545
it("throw an exception if wrong type is extracted from the built JSON") {
46-
val json = obj("date" -> JDate(parseDate("2011-11-11 11:11")))
46+
val json = toJson(Map("date" -> JDate(parseDate("2011-11-11 11:11"))))
4747

4848
intercept[ZeisonException] {
4949
json.date.toInt

0 commit comments

Comments
 (0)