Tuesday, September 08, 2009

Proposed json.plt change

I'm not sure how many users I have of my json.plt PLaneT package, nor how many of them read my blog. But I thought I'd see if I could take a straw poll here. I'm thinking about changing the data definition in a backwards-incompatible way. What if I said:
A jsexpr is one of:
  • 'null
  • boolean
  • string
  • integer
  • inexact-real
  • (vectorof jsexpr)
  • (listof (cons symbol jsexpr))
The nice thing about this representation is that it's easier to quote and quasiquote. The down-sides are that array manipulation is a little less convenient, and table lookup is slower.

Another alternative is:
A jsexpr is one of:
  • #:null
  • boolean
  • string
  • integer
  • inexact-real
  • (listof jsexpr)
  • (listof (cons symbol jsexpr))
The nice thing about this is that both arrays and tables are conveniently represented as lists. But it's a little uglier for representing null, which is necessary to avoid ambiguity between the JSON strings { "null" : [] } and [[null]]. Note that it's also a little more subtle to distinguish between arrays and tables.

Other possible unambiguous representations of null include #\null, #"null", or #&0. Yech.

If you have any opinions, feel free to comment here or email me privately.

Update: Whoops, can't have them both be lists, because of the ambiguity between the empty object and empty array.


Simon Haines said...

I use json.plt, mainly to serialise hashes for javascript consumption. I think the second alternative seems more flexible by not requiring vectors in order to produce json arrays. I guess the convenience is determined by whether the client naturally uses vectors or lists. I guess both could be accommodated in the cond statement of 'write' in json.ss, but what about 'read'? If you need to make a determination one way or the other, I personally would opt in favour of lists.

As for null representation, I suspect this may purely come down to a matter of taste. Personally, I find either 'null or #\null the least offensive, aesthetically.

Be bold. Cower not before the false portent of backwards compatibility. When using third-party libraries, good practice mandates coding against specific versions of the library anyway. So go ahead and make the change--your users will either adopt it or continue with what already works for them.

Dave said...

I agree with Simon that, on average, it's more convenient to represent arrays as lists.

This means you'd need an alternative representation for objects. Hash tables are the current choice, but as you mentioned to me the other day they are less convenient for quoting because you can't do:

'#hash((,unquoted-expr . value))

Just thinking out loud... How about wrapping hashes in an alist inside a prefab struct?

(define-struct json-object (values) #:prefab)

Then you could do:

'#s(json-object ((,unquoted-expr . value)))

It's quotable and it means you can use lists to represent arrays, but it certainly isn't as neat as using a primitive Scheme type.

Felix said...

The {{{#\nul}}} character for {{{null}}} ! Brilliant hack!