Quantcast

better type safety in Json response

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

better type safety in Json response

chris_lewis
Hi all,

When I added the Json response, I believe the required input was JObject, which is too restrictive and relaxed to JValue. The problem with JValue, however small, is that it has subtypes for which there are no valid serialized formats (JNothing, JField). I've pushed an experimental fix for this, available here:

https://github.com/chrislewis/Unfiltered/compare/jserializable

The solution introduces the type class JSerializable of which only valid instances are available (namely JObject, JArray, JNull.type, JDouble, JInt, JString, and JBool). One could argue this isn't really that important, but it remains that the current implementation can result either a) throw a runtime exception if passed JNothing or b) deliver invalid json to the client if given JField.

-chris
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: better type safety in Json response

eed3si9n
hi chris,

I relax it to JValue since json allows arrays and values.

One thing I noticed in your test is that `"answer" -> Seq(42)` needed to be explicitly assigned to a JObject.
I am assuming you had to change it because it's just Tuple2[String, Seq[Int]],
which turns into JObject by virtue of lift-json implicits, and plain Tuple2[String, Seq[Int]] wasn't recognized to be JSerializable.

before:
    case GET(UFPath("/jsonp/lift-json/optional") & Jsonp.Optional(callback)) => callback respond {
      import net.liftweb.json.JsonAST._
      import net.liftweb.json.JsonDSL._
      "answer" -> Seq(42)
    }

after:
    case GET(UFPath("/jsonp/lift-json/optional") & Jsonp.Optional(callback)) => callback respond {
      import net.liftweb.json.JsonAST._
      import net.liftweb.json.JsonDSL._
      val obj: JObject = ("answer" -> Seq(42))
      obj
    }

I personally think JValue is good enough, but I wonder if there's a clean way to allow `"answer" -> Seq(42)` as before
without reimplementing the DSL.

eugene

On Tue, Mar 29, 2011 at 5:47 PM, chris_lewis [via Databinder] <[hidden email]> wrote:
Hi all,

When I added the Json response, I believe the required input was JObject, which is too restrictive and relaxed to JValue. The problem with JValue, however small, is that it has subtypes for which there are no valid serialized formats (JNothing, JField). I've pushed an experimental fix for this, available here:

https://github.com/chrislewis/Unfiltered/compare/jserializable

The solution introduces the type class JSerializable of which only valid instances are available (namely JObject, JArray, JNull.type, JDouble, JInt, JString, and JBool). One could argue this isn't really that important, but it remains that the current implementation can result either a) throw a runtime exception if passed JNothing or b) deliver invalid json to the client if given JField.

-chris

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: better type safety in Json response

chris_lewis
On 4/4/11 11:27 AM, eed3si9n [via Databinder] wrote:
hi chris,

Hi!
I relax it to JValue since json allows arrays and values.
Yeah, and also strings, ints, bools, and nulls.

One thing I noticed in your test is that `"answer" -> Seq(42)` needed to be explicitly assigned to a JObject.
I am assuming you had to change it because it's just Tuple2[String, Seq[Int]],
which turns into JObject by virtue of lift-json implicits, and plain Tuple2[String, Seq[Int]] wasn't recognized to be JSerializable.
Right.

before:
    case GET(UFPath("/jsonp/lift-json/optional") & Jsonp.Optional(callback)) => callback respond {
      import net.liftweb.json.JsonAST._
      import net.liftweb.json.JsonDSL._
      "answer" -> Seq(42)
    }

after:
    case GET(UFPath("/jsonp/lift-json/optional") & Jsonp.Optional(callback)) => callback respond {
      import net.liftweb.json.JsonAST._
      import net.liftweb.json.JsonDSL._
      val obj: JObject = ("answer" -> Seq(42))
      obj
    }

I personally think JValue is good enough, but I wonder if there's a clean way to allow `"answer" -> Seq(42)` as before
without reimplementing the DSL.
It is a bit of a bummer - there's probably cleaner way but I haven't had the time to clean it up yet. My issue with JValue is that it's not type-safe in that it allows invalid content to be streamed as if it were valid JSON. This can be resolved at the type level, and I want to exploit that. I agree that losing the lift DSL sucks, yet I still prefer static guarantees. I'll make some time to find a solution - if you have any input please share :-).

Honestly, I think it makes sense for JSerializable (or something like it) to be part of the core lift-json lib. It's understandable its AST uses intermediate types to represent components of a JSON document, and that not every intermediate type is representable as JSON. However I am surprised that the serializable components aren't represented by a higher-level type. Perhaps I should chat with the lift folks ...

-chris

eugene

On Tue, Mar 29, 2011 at 5:47 PM, chris_lewis [via Databinder] <[hidden email]> wrote:
Hi all,

When I added the Json response, I believe the required input was JObject, which is too restrictive and relaxed to JValue. The problem with JValue, however small, is that it has subtypes for which there are no valid serialized formats (JNothing, JField). I've pushed an experimental fix for this, available here:

https://github.com/chrislewis/Unfiltered/compare/jserializable

The solution introduces the type class JSerializable of which only valid instances are available (namely JObject, JArray, JNull.type, JDouble, JInt, JString, and JBool). One could argue this isn't really that important, but it remains that the current implementation can result either a) throw a runtime exception if passed JNothing or b) deliver invalid json to the client if given JField.

-chris




If you reply to this email, your message will be added to the discussion below:
http://databinder.3617998.n2.nabble.com/better-type-safety-in-Json-response-tp6221079p6239013.html
To start a new topic under Unfiltered, email [hidden email]
To unsubscribe from Unfiltered, click here.

Loading...