Skip to content

Commit

Permalink
remove Json.apply() methods and simplify Json.arr() usage
Browse files Browse the repository at this point in the history
  • Loading branch information
Narigo authored and galderz committed Oct 25, 2013
1 parent c9c3f6f commit 10f8fa9
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 81 deletions.
18 changes: 1 addition & 17 deletions src/main/scala/org/vertx/scala/core/json/Json.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,6 @@ object JsonElemOps {
*/
object Json {

/**
* Constructs a JsonObject from a fieldName -> value pairs.
*
* @param fields The fieldName -> value pairs
* @return A JsonObject containing the name -> value pairs.
*/
def apply(fields: (String, Any)*): JsonObject = obj(fields: _*)

/**
* Creates a JsonArray from a sequence of values.
*
* @param elements The elements to put into the JsonArray.
* @return A JsonArray containing the provided elements.
*/
def apply(elements: Seq[Any]): JsonArray = arr(elements)

/**
* Creates a JsonArray from an encoded JSON string.
*
Expand Down Expand Up @@ -133,7 +117,7 @@ object Json {
* @param elements The elements to put into the JsonArray.
* @return A JsonArray containing the provided elements.
*/
def arr(fields: Seq[Any]): JsonArray = {
def arr(fields: Any*): JsonArray = {
val a = new JsonArray()
fields.foreach(f => addToArray(a, f))
a
Expand Down
87 changes: 23 additions & 64 deletions src/test/scala/org/vertx/scala/tests/core/json/JsonTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.vertx.scala.core.json._

/**
* @author Edgar Chan
* @author <a href="http://www.campudus.com/">Joern Bernhardt</a>
*/
class JsonTest {

Expand All @@ -34,16 +35,14 @@ class JsonTest {
"foo" -> "foo text",
"bar" -> 3.45d,
"baz" -> false,
"myInt" -> Integer.MAX_VALUE
)
"myInt" -> Integer.MAX_VALUE)

assertEquals("foo text", obj.getString("foo"))
assertEquals(3.45d, obj.getValue[Double]("bar"), 1e-15)
assertEquals(false, obj.getBoolean("baz"))
assertEquals(Integer.MAX_VALUE, obj.getInteger("myInt"))
assertEquals(enc, obj.encode())


}

@Test
Expand All @@ -55,7 +54,7 @@ class JsonTest {
val scalaMapFields: scala.collection.Map[String, AnyRef] = wrapped.asMap

//Get the original object
val obj2:JsonObject = wrapped
val obj2: JsonObject = wrapped

assertEquals("foo text", scalaMapFields("foo"))
assertEquals(true, obj2.getBoolean("optional"))
Expand All @@ -66,86 +65,46 @@ class JsonTest {
def jsonArrayTest() {

val enc = """["f",3,"b",7,35.4,true]"""
val array = Json.arr(List("f", 3, "b", 7, 35.4f, true))
val array = Json.arr("f", 3, "b", 7, 35.4f, true)

assertEquals(6, array.size())
assertEquals(enc, array.encode())
}


@Test
def customObjTest(){
def customObjTest() {
import java.util.Date

case class Custom(date:Date, other:Boolean)
case class Custom(date: Date, other: Boolean)
val info = Custom(new Date(), false)
val obj1 = Json.obj("custom" -> info)
val obj1 = Json.obj("custom" -> info)

assertEquals(info, obj1.getValue[Custom]("custom"))
}

@Test
def nestedObjectsTest(){
def nestedObjectsTest() {
val obj =
Json.obj(
"webappconf" -> Json.obj(
"port" -> 8080,
"ssl" -> false,
"bridge" -> true,
"inbound_permitted" -> Json.arr(
Seq(Json.obj(
"address" -> "acme.bar",
"match" -> Json.obj(
"action" -> "foo"
)),
Json.obj(
"address" -> "acme.baz",
"match" -> Json.obj(
"action" -> "index"
))
)
),
"outbound_permitted" -> Json.arr(
Seq(new JsonObject())
)
)
)

assertEquals(jsonString, obj.encode())
}


@Test
def nestedObjectsShorterVersionTest(){
val obj =
Json(
"webappconf" -> Json(
"port" -> 8080,
"ssl" -> false,
"bridge" -> true,
"inbound_permitted" -> Json(
Seq(Json(
"address" -> "acme.bar",
"match" -> Json(
"action" -> "foo"
)),
Json(
"address" -> "acme.baz",
"match" -> Json(
"action" -> "index"
))
)
),
"outbound_permitted" -> Json(
Seq(new JsonObject())
)
)
)
"webappconf" -> Json.obj(
"port" -> 8080,
"ssl" -> false,
"bridge" -> true,
"inbound_permitted" -> Json.arr(
Json.obj(
"address" -> "acme.bar",
"match" -> Json.obj(
"action" -> "foo")),
Json.obj(
"address" -> "acme.baz",
"match" -> Json.obj(
"action" -> "index"))),
"outbound_permitted" -> Json.arr(
new JsonObject())))

assertEquals(jsonString, obj.encode())
}


private def jsonString = {
"""
|{
Expand Down

10 comments on commit 10f8fa9

@tsuna
Copy link

@tsuna tsuna commented on 10f8fa9 Nov 1, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the rationale behind the removal of Json.apply()?

@galderz
Copy link
Contributor

@galderz galderz commented on 10f8fa9 Nov 8, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed it here. We made it more explicit from a factory method perspective whether you are creating a JSON object or array. Did you prefer the old way with apply() as central factory method? Or where you using JSON objects for some pattern matching cases?

@tsuna
Copy link

@tsuna tsuna commented on 10f8fa9 Nov 8, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just didn't see why Json.obj(...) was suddenly preferred to the shorter Json(...)

On a side note, I also needed a few minutes to realize that I needed to change my Json.arr(someSeq) to Json.arr(someSeq: _*) after this change.

@Narigo
Copy link
Member Author

@Narigo Narigo commented on 10f8fa9 Nov 8, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tsuna The problem is that you'd never really know if you use apply() for JsonObject or JsonArray. If we'd allow it, then only for one kind and which one should we prefer? Probably JsonObject, but people reading the code will always have to think about that first. Writing these 4 characters to make it explicit is probably better.

I saw the Json.arr(someSeq: _*) too and am trying to mitigate this by matching for Sequences and directly converting them into JsonArrays if you're in Json.obj(...) or Json.arr(...). But I still have a problem when you have a recursive List, for example Json.obj("some_list" -> List(1, 2, List(3, 4))) -> { "some_list" : [1, 2, []] }. Need to check that and I'll add something so working with lists will be easier again.

Sorry for the inconvenience regarding this API breaking, but we're still not at 1.0 and we're trying to find the best things for users. If you have suggestions, please shoot :)

@Narigo
Copy link
Member Author

@Narigo Narigo commented on 10f8fa9 Nov 8, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed my problem (stupid me) and made a PR: #82

@galderz
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Narigo Maybe, in order to follow the traditional method of using apply() as factory method (instead of arr, or obj names), you could have two companion objects, one for JsonObject and one for JsonArray, and then in each have an apply() method that takes the expected parameters? I think this would be more intuitive:

object JsonObject {
  def apply() ....
}

object JsonArray {
  def apply() ....
}

You'd loose the methods in Json, but i don't think that's bad. People are already having to decide between obj or arr, which is the same as chosing between JsonArray() and JsonObject()

Thoughts?

@Narigo
Copy link
Member Author

@Narigo Narigo commented on 10f8fa9 Nov 12, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@galderz We could provide both, JsonObject.apply(str: String) = new JsonObject(str) and JsonArray.apply(str: String) = new JsonArray(str). I somehow like the shorter Json.arr . Json.obj form, especially as you can import Json._ and use them directly in the very short form of arr() and obj().

@galderz
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Narigo I had a look at other Json libraries (i.e. Play! 2) and they don't use apply() as factories, so let's leave it as is. I'd like our methods to be consistent though in their naming:

fromArrayString
fromObjectString
emptyArr
emptyObj
obj
arr
addToArray
addToObject

^ I think all methods should say the full word array or object to be consistent. So, emptyArray, emptyObject, array, object. Thoughts?

@Narigo
Copy link
Member Author

@Narigo Narigo commented on 10f8fa9 Nov 14, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I ever used fromArrayString or fromObjectString. Guess an apply(json: String): JsonElement where a JsonElement can only be a JsonArray or JsonObject would be a better idea. Are addToArray and addToObject public? Is there a reason why?

If you want to change arr and obj, I don't mind too much - but we'd have to change all the client code again.

...and I admit I kind of like the piratey feeling I got from writing arr all the time. ;)

@galderz
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I ever used fromArrayString or fromObjectString. Guess an apply(json: String): JsonElement where a JsonElement can only be a JsonArray or JsonObject would be a better idea.

Wouldn't that lead to casting on the client side?

Are addToArray and addToObject public? Is there a reason why?

Right now we are relying on the Java JSON classes, we should probably have our own JsonArray and JsonArray to which you can add/remove items.

Yeah, i think I'd rather have full names, particularly for small names such as array and object. I'll add an issue for this and I owe you a beer ;)

Please sign in to comment.