[netmod] json empty leaf encoding strangeness [Re: WG Last Call for draft-ietf-netmod-yang-json-04 (until 2015-06-29)]

Christian Hopps <chopps@chopps.org> Sat, 18 December 2021 06:47 UTC

Return-Path: <chopps@chopps.org>
X-Original-To: netmod@ietfa.amsl.com
Delivered-To: netmod@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id DBA353A0C3E for <netmod@ietfa.amsl.com>; Fri, 17 Dec 2021 22:47:29 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.896
X-Spam-Level:
X-Spam-Status: No, score=-1.896 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HTML_MESSAGE=0.001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id IZgD0qRFGUR8 for <netmod@ietfa.amsl.com>; Fri, 17 Dec 2021 22:47:24 -0800 (PST)
Received: from smtp.chopps.org (smtp.chopps.org [54.88.81.56]) by ietfa.amsl.com (Postfix) with ESMTP id 80FEA3A0C3B for <netmod@ietf.org>; Fri, 17 Dec 2021 22:47:24 -0800 (PST)
Received: from smtpclient.apple (047-026-251-217.res.spectrum.com [47.26.251.217]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by smtp.chopps.org (Postfix) with ESMTPSA id DFE057D001; Sat, 18 Dec 2021 06:47:22 +0000 (UTC)
From: Christian Hopps <chopps@chopps.org>
Message-Id: <1640D503-A676-4BC5-82E6-E08ED04F7106@chopps.org>
Content-Type: multipart/alternative; boundary="Apple-Mail=_73D51FBB-488F-45BA-A9FA-49E613EC91C4"
Mime-Version: 1.0 (Mac OS X Mail 15.0 \(3693.40.0.1.81\))
Date: Sat, 18 Dec 2021 01:47:21 -0500
In-Reply-To: <m2lhf27sko.fsf@birdie.labs.nic.cz>
Cc: Christian Hopps <chopps@chopps.org>, Juergen Schoenwaelder <j.schoenwaelder@jacobs-university.de>, Ladislav Lhotka <lhotka@nic.cz>
To: "netmod@ietf.org" <netmod@ietf.org>
References: <D1A4CEB7.B22F7%kwatsen@juniper.net> <20150624145325.GB38016@elstar.local> <m2lhf27sko.fsf@birdie.labs.nic.cz>
X-Mailer: Apple Mail (2.3693.40.0.1.81)
Archived-At: <https://mailarchive.ietf.org/arch/msg/netmod/0oLiIc20O86UmKcwkSptJ9bLmdA>
Subject: [netmod] json empty leaf encoding strangeness [Re: WG Last Call for draft-ietf-netmod-yang-json-04 (until 2015-06-29)]
X-BeenThere: netmod@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: NETMOD WG list <netmod.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/netmod>, <mailto:netmod-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/netmod/>
List-Post: <mailto:netmod@ietf.org>
List-Help: <mailto:netmod-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/netmod>, <mailto:netmod-request@ietf.org?subject=subscribe>
X-List-Received-Date: Sat, 18 Dec 2021 06:47:30 -0000

Hi,

I was just going over json encoding of YANG, and got to the empty leaf encoding and it's odd use of "[null]" rather than just "null". I read the explanation, but had a hard time believing what it said. So, running code time. The first thing I tried was Python to see if something weird happened:

In [1]: import json
In [2]: json.loads('{"foo": null}')
Out[2]: {'foo': None}

Nope, seems fine. Then checked the "definitive source" for json, javascript:

js> JSON.parse("{\"foo\": 1, \"bar\": null}")
({foo:1, bar:null})

Seems fine here too.. 

So I went searching the mailing list and found this:

> On Jun 29, 2015, at 5:49 AM, Ladislav Lhotka <lhotka@nic.cz> wrote:

> Juergen Schoenwaelder <j.schoenwaelder@jacobs-university.de> writes:

...
>> - I am not sure I understand the argument why [null] is better than

>>  null for the empty type. Perhaps it is but the text does not really

>>  tell me.

> 

> "foo": null

> 

> may sometimes appear as if the "foo" instance is not present at all - in

> some languages this is probably more serious than in others. This is how

> it works in Python:

> 

>>>> import json

>>>> obj = json.loads('{"foo": null, "bar": [null]}')

>>>> "YES" if obj["foo"] else "NO"

> 'NO'

>>>> "YES" if obj["bar"] else "NO"

> 'YES'

> 

> So the special value "[null]" seems safer and it cannot appear in any

> other context.

The justifying example here is, unfortunately, wrong. One does not (normally) check for the presence of a dictionary item in python by trying to access the value of that item (which is what the code above is doing). The standard python code to check for the presence of an item is as follows, and it works fine with a "null" json value:

In [1]: import json
In [2]: o = json.loads('{"foo": null}')
In [3]: o
Out[3]: {'foo': None}
In [4]: "YES" if "foo" in o else "NO"
Out[4]: 'YES'

Indeed in python if you try and check for a missing item the way the email above describes, and the item is missing, an exception is raised:

In [5]: o["bar"]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)

One *could* catch the "KeyError" to check for missing items which will also work using "null" son values for empty leafs, but the more common form is "if key in dict" in my experience.

Furthermore, using "access the value" for presence check will also "fail" for zero values and for empty strings, but we don't have odd encodings for integers or strings...

In [1]: import json
In [2]: o = json.loads('{"foo": 0, "bar": ""}')
In [3]: o
Out[3]: {'foo': 0, 'bar': ''}
In [4]: "YES" if o["foo"] else "NO"
Out[4]: 'NO'
In [5]: "YES" if o["bar"] else "NO"
Out[5]: 'NO'

Point being, evaluating an items value is not the right way to check for "presence", it's the way to check the "value" of the item. An empty leaf has no value so it's basically never correct to try to access that value in code.

Javascript is basically the same as python here:

js> o = JSON.parse('{"foo": null}')
({foo:null})
js> if ("foo" in o) { "YES" } else { "NO" }
"YES"

So, do we think it would it ever be possible to change (fix) this encoding oddity?

Thanks,
Chris.