Subject: [calsify] New Version of the iCalendar in JSON (jCal) draft, feedback requested

From: Philipp Kewisch <[email-masked]>
Date: Tue, 15 Jan 2013 09:53:49 +0100

Hello Folks,

Based on discussion we have had within the calconnect group, I have just 
posted a new version of draft-kewisch-et-al-icalendar-in-json with the 
following changes. You can find the draft here 
<http://www.ietf.org/id/draft-kewisch-et-al-icalendar-in-json-01.txt>.

       *  Added information on how to handle multi-value parameter.  The
          decision leads to a cleaner draft for a similar proposal for
          vcard.

       *  Removed the open discussion point section regarding the mime
          media type in favor of adding one.

I would appreciate your feedback on the draft in order to advance on 
this topic.

Also, especially or the vcarddav folks, please also take a look at my 
previous email 
<http://www.ietf.org/mail-archive/web/vcarddav/current/msg02678.html> to 
get a comparison between the vcarddav-json draft and the format we 
propose for iCalendar. I would like to push forward with this and come 
to a consensus so we can provide a compatible draft for vcards.

I am also happy to announce that Mozilla is already testing this draft 
in the field with the Firefox OS calendaring application. To do so, we 
are using the ical.js library I have been working on, see 
<https://github.com/kewisch/ical.js/>.

Regards,
Philipp

---

From: Scotty Logan <[email-masked]>
Date: Tue, 15 Jan 2013 11:06:12 -0800

I've been lurking on this list, but this caught my eye since I've been
working with a lot of JSON recently.

I think that's the most un-JSON-like JSON I've ever seen.  If you're
going to use JSON, please use the ON part, and use objects to
represent non-array data. The example in B.2.2. would be easier to
work with if it was more JSON-ish:

{
    "prodid": "-//Example Corp.//Example Client//EN"],
    "version": "2.0",
    "vtimezones": [
        {
            "tzid": "US/Eastern",
            "last-modified": "2004-01-10T03:28:45Z",
            "daylight": {
                "tzname": "EDT",
                "tzoffsetfrom": "-05:00",
                "tzoffsetto": "-04:00",
                "dtstart": "2000-04-04T02:00:00",
                "rrule": {
                    "freq": "yearly",
                    "byday": "1su",
                    "bymonth": 4
                },
            },
            "standard": {
                "tzname": "EST",
                "tzoffsetfrom": "-04:00",
                "tzoffsetto": "-05:00",
                "dtstart": "2000-10-26T02:00:00",
                "rrule": {
                    "freq": "yearly",
                    "byday": "1su",
                    "bymonth": 10
                }
            }
        }
    ],
    "vevents": [
        {
            "dtstamp": "2006-02-06T00:11:21Z",
            "dtstart": {
                "tzid": "US/Eastern",
                "type": "date-time",
                "value": "2006-01-02T12:00:00"
            },
            "duration": "PT1H",
            "rrule": {
                "freq": "daily",
                "count": 5
            }
            "rdate": {
                "tzid": "US/Eastern",
                "type": "period",
                "value": "2006-01-02T15:00:00/PT2H"
            },
            "summary": "Event #2",
            "description": "We are having ... 12 pm meetings.",
            "uid": "[email-masked]"
        },
        {
            "dtstamp": "2006-02-06T00:11:21Z",
            "dtstart": {
                "tzid": "US/Eastern",
                "type": "date-time",
                "value": "2006-01-02T14:00:00"
            },
            "duration": "PT1H",
            "recurrence-id": {
                "tzid": "US/Eastern",
                "type": "date-time",
                "value": "2006-01-04T12:00:00"
            },
            "summary": "Event #2 bis",
            "uid": "[email-masked]"
        }
    ]
}

Now the data can be processed with code like:

    var jcal = getJCalData(…);

    jcal.vevents.forEach(function (vevent) {

        var dtstart = null;

        if (typeof vevent.dtstart === 'string') {
           dtstart = new Date(vevent.dtstart);
        } else {
            if (vevent.dtstart.tzid) {
                …
            }
            …
        }
        ...
    }

 Scotty

On Tue, Jan 15, 2013 at 12:53 AM, Philipp Kewisch <[email-masked]> wrote:
> I would appreciate your feedback on the draft in order to advance on this
> topic.
>
> <http://www.ietf.org/mail-archive/web/vcarddav/current/msg02678.html> to get
> a comparison between the vcarddav-json draft and the format we propose for
> iCalendar. I would like to push forward with this and come to a consensus so
> we can provide a compatible draft for vcards.
>
> I am also happy to announce that Mozilla is already testing this draft in
> the field with the Firefox OS calendaring application. To do so, we are
> using the ical.js library I have been working on, see
> _______________________________________________
> calsify mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/calsify
>

---

From: Cyrus Daboo <[email-masked]>
Date: Fri, 18 Jan 2013 09:51:51 -0500

Hi Simon,

--On January 18, 2013 3:47:43 PM +0100 Simon Perreault 
<[email-masked]> wrote:

>> According to the specs, jCard supports 2.1 and 3.0, not just version 4.
>
> This is wrong, it should only support version 4. Doing otherwise would be
> asking for a lot of trouble.

That would be one way to encourage more adoption of version 4, which would 
be a good thing IMHO.

-- 
Cyrus Daboo

---

From: Philipp Kewisch <[email-masked]>
Date: Sat, 26 Jan 2013 09:43:10 +0100

Hi Scotty,

I understand that the JSON you see here is slightly different than what 
you often see (root being an object), but the data we have to handle 
here is slightly different too. What we have here is definitly ON, as in 
Javascript, Arrays are also Objects and Arrays are also part of the JSON 
spec.

The JSON you provide looks very much like what I started with when I was 
working on my library to parse iCalendar data, but as we progressed with 
the spec, more and more flaws came up. Remember we are designing a data 
format, not a library to process it. Let me show you some examples of 

>      "prodid": "-//Example Corp.//Example Client//EN"],
What rule would this go by? Use the component name and add 's' ?
>              "last-modified": "2004-01-10T03:28:45Z",
What happens if there are multiple daylight components? Even if thats 
not possible in this case, it could for other components so there would 
have to be lots of per-component exceptions which is neither consistent 
nor future proof.

>                  "value": "2006-01-02T12:00:00"
So dates can have two different formats? What to use when? What if there 
is a parameter named TYPE ?

>              "uid": "[email-masked]"
What happens with properties that can occur multiple times or have 
multiple values (like CATEGORIES)?

My next idea back then was to turn it into an array, i.e "category": 
["abc", "def"], but then you run into consistency/performance issues 
again. Add an array for everything, i.e "summary": ["Event #2"] or do 
type checking each time?
>      jcal.vevents.forEach(function (vevent) {
While I understand it would be nice to process jCal without a library 
(and you can, even with our draft), in many cases you will just end up 
duplicating code that a js library will provide to you. The easier we 
make this, the more likely it is that people will produce wrong jCal, 
because their code evolves from something simple.

I hope this give you a better feeling with the format we propose, let me 
know what you think!
Philipp

---

From: Philipp Kewisch <[email-masked]>
Date: Sat, 26 Jan 2013 09:43:50 +0100

TL;DR; version at the end of this email.

On 1/16/13 2:24 AM, Michael Angstadt wrote:
> (1) Grouping
>
> A simple solution would be to prepend the group to the property name,
> separating it from the property name with some special character, just
> like in vCard.  For example:
>
> ["group.email", {}, "text", "[email-masked]"]
>
> (a) Greater compatibility with jCal.
> (b) Grouping is a fairly infrequently-used feature.  Changing the
> syntax would add extra complexity which won't be used in most
> situations.
I agree, I had thought about grouping, but I preferred a similar syntax 
so a library that could parse jCal could also parse jCard. For a simple 
solution, I'd go with just using the whole thing as a property name like 
you posted:

["group.email", {}, "text", "[email-masked]"]

Another option that would allow same property names as group names is to 
add a special type "group" in the jCard spec.

["groupname", {}, "group", [
     ["email", {}, "text", "[email-masked]"]
   ]
]

Which would serialize to:

groupname.EMAIL:[email-masked]

This would differ from a property named groupname:

["groupname", {}, "text", "foo"]

and due to the fact that properties are in an array and not in an 
object, there is no problem keeping both. The downside for this 
alternative is that there is an extra set of parameters that does not 
serialize back to iCalendar/vCard. This would "look" correct but be invalid:

["groupname", { "x-bogus": "param" }, "group", [
     ["email", { "x-ok": "param" }, "text", "[email-masked]"]
   ]
]

And still serialize to the following, dropping x-bogus.

groupname.EMAIL;X-OK=param:[email-masked]

> (3) JSON objects for property values
>
> On the flip-side, I think one nice feature about vcarddav-json is that
> property values are encoded as JSON objects.  This is great for
> multi-valued properties like ADR and N because each value can be
> indexed by a human-readable name.  jCal, however, requires that the
> values be appended onto the end of the property array, which means
> that they must be retrieved by index.  It also means that a
> placeholder element (like a "null" value) must be included for any
> missing components of the property value in order to preserve the
> array indexing.  The ADR property is a good example:
We've discussed this in the last TC-XML-JSON call, related to a 
different issue. I think this is something we could find a consensus on 
and put it into the jCal spec. On the one hand I would like to avoid 
making property values too diverse and just stay with not splitting the 
text at all:

["adr", {"type":"work"}, "text", ";2875 boul. Laurier, suite 
D2-630;Quebec;QC;G1V 2M2;CA"]

This would leave the parsing to a library. For jCal this would be 
sufficient, since the allowed text in an RRULE property value is 
limited, so its just a matter of val.split(";").forEach(function(part) { 
let k,v = part.split("="); map[k] = v }); if the library needs to access 
the parts in a map. Reasons that speak for against using objects (or 
even arrays) for structured values:

* Slight performance loss, which might add up, due to:
    ** Need for either special-casing of type per property or, to be 
safe, for every property.
    ** Additional Objects per property, which might not be needed every 
time.
* Breaks consistency. Which properties are allowed to have objects?
* What about unknown properties added via extension? What would this 
parse to:  X-MYTHING:LoOKS=;LIKE=;A=;STrUCTURED=;VAlUE=
   ** ["x-mything", {}, "text", { "looks": "", "like":"", 
"a":"","structured":"","value":"" }]
   ** ["x-mything", {}, "text", "LoOKS=;LIKE=;A=;STrUCTURED=;VAlUE="]
* If unknown objects should have a default, what separator to choose?
* For jCal, this is only valid for RRULE, which you will need a library 
anyway to process gracefully (calculate occurrences)

On the other hand, especially with vcard in mind, I can see this is 
useful. Specifically for jCal, we have discussed that it would be good 
to change GEO and REQUEST-STATUS a single-value property where the value 
is an array, i.e ["geo", {}, "float", [12.34, 56.78]]. In line with 
this, we could also allow using an object for RRULE since it has its own 
type.

 From your vCard example it seems to me that /any/ "text" value can be 
structured, so we would need to make using objects as property values 
something that is generally allowed for and warn parser implementers 
that they need to check the value type. To handle the issue with unknown 
properties, we could assert that if the parser does not know about the 
property that it should treat it as opaque text.

So let me summarize whats left to decide:

(1) Grouping:
   a) Leave "groupname.email" as the property name, or
   b) Add a pseudo-property with the special type "group" and make its 
value be an array of group members

(2) Naming conflicts: We agree here that jCal's mechanism works better

(3) Objects for structured property values
   a) Use an array, possibly with a null value for any structured property
   b) Use an object, avoids null values and makes access easier
   c) Do not parse value at all, leave it as an opaque text

My personal preferences are 1a and either 3b or 3c.

Philipp

---

From: Scotty Logan <[email-masked]>
Date: Tue, 29 Jan 2013 13:35:27 -0800

On Sat, Jan 26, 2013 at 12:43 AM, Philipp Kewisch <[email-masked]> wrote:
> I understand that the JSON you see here is slightly different than what you
> often see (root being an object),

I started out with a response to each of your points, but then it
occurred to me that the problem isn't in the naming ("vtimezone" vs
"vtimezones"), or representing values as arrays or strings:  the
problem, as I see it, is that the JSON draft appears to be an attempt
to convert the iCalendar format into JSON, rather than creating a JSON
representation of the iCalendar data model.

  Scotty