Re: [Json] A possible summary of the discussion so far on code points and characters

R S <> Sun, 09 June 2013 04:48 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id C483021F92B8 for <>; Sat, 8 Jun 2013 21:48:07 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -2.383
X-Spam-Status: No, score=-2.383 tagged_above=-999 required=5 tests=[AWL=0.216, BAYES_00=-2.599, HTML_MESSAGE=0.001, NO_RELAYS=-0.001]
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id SYGsfIpwX17W for <>; Sat, 8 Jun 2013 21:48:06 -0700 (PDT)
Received: from ( [IPv6:2a00:1450:400c:c00::235]) by (Postfix) with ESMTP id 2A98721F91B1 for <>; Sat, 8 Jun 2013 21:48:05 -0700 (PDT)
Received: by with SMTP id y10so1616565wgg.20 for <>; Sat, 08 Jun 2013 21:48:04 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=jFSwIaNubTzPLpdIl8MuHMNPUlYRXAsOF0yjF1PoGzI=; b=EGkG9rOyTr4pr4AJsQt3X/8XEIWkD76ltezX0I81OrmK+mKXYx06eVHl2sVSF7p1Jl RiQPd1OBhIng+/rADoL6Jed8KCAEtuiTAbTfdmHu8jaZzQg7nLISecmJoF14F8KO7e45 zMOQ6LDHZZyXEhb9XXi21Umv90Qv0gqEZ9fcvGQQhlHkj3VtL9cjWJhTX5pY1qz9Ink5 FE1ys6LV7SWCLKQoy+K4vcMZiHXX0tIy53ve5PECyeY+rMP/+xOyj/j18SNbMsPgBajY Sa5wqOfO8oQzTWMyRwN99NcLLalWC74TVFKAVBu8zaKatj2SNPGKtvdDTRTOry3cg2Qj Y49w==
MIME-Version: 1.0
X-Received: by with SMTP id j5mr2592658wjs.79.1370753284261; Sat, 08 Jun 2013 21:48:04 -0700 (PDT)
Received: by with HTTP; Sat, 8 Jun 2013 21:48:04 -0700 (PDT)
In-Reply-To: <>
References: <> <> <> <> <> <>
Date: Sat, 8 Jun 2013 21:48:04 -0700
Message-ID: <>
From: R S <>
To: Carsten Bormann <>
Content-Type: multipart/alternative; boundary=047d7ba9751895783d04deb15e02
Cc: "" <>
Subject: Re: [Json] A possible summary of the discussion so far on code points and characters
X-Mailman-Version: 2.1.12
Precedence: list
List-Id: "JavaScript Object Notation \(JSON\) WG mailing list" <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Sun, 09 Jun 2013 04:48:09 -0000

On Sat, Jun 8, 2013 at 7:29 PM, Carsten Bormann <> wrote:
> Changing the JSON spec retroactively to put in a requirement for handling
> strings in UTF-16 code units so that unpaired surrogates might work more
> uniformly is something different.

I haven't proposed a change to the spec--have you? I'm fine with the status
quo: vaguely referring to Unicode characters with the full knowledge that
JSON is intended to produce identical results to JavaScript's eval function
for the subset of JavaScript syntax that JSON supports.

> (BTW, your examples show that two JSON implementations handle Unicode
> non-characters nicely, which is great and probably something to be
> recommended, but doesn't have anything to do with switching to UTF-16 code
> units.  Now let's put in a couple of (paired!) surrogates to show how well
> the code units work:
> >>> print(json.loads('{"a": "\ud800\udd51" }')["a"])
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> UnicodeEncodeError: 'utf-8' codec can't encode character '\ud800' in
> position 0: surrogates not allowed
> >>> print(json.loads('{"a": "\\ud800\\udd51" }')["a"])
> 𐅑
> ... which demonstrates nicely what I have been saying: Don't put unescaped
> surrogates into your JSON texts, because there is no equivalence at the
> UTF-16 code unit level.)

That must be Python3. That shell session is a little misleading, because
it's the print function throwing the exception. The Python3 JSON parser
accepts both, and the Python3 JSON encoder produces identical output from
those inputs. Although they do in Python 2.7, the two inputs don't compare
as equal in Python 3. However, both JSON messages seem unambiguous to
Python's JSON encoder.

~$ python
Python 2.7.3 (default, Sep 26 2012, 21:53:58)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import json
>>> json.loads('{"a": "\\ud800\\udd51"}')["a"] ==  json.loads('{"a":

~$ python3
Python 3.2.3 (default, Sep 30 2012, 16:43:30)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import json
>>> json.loads('{"a": "\\ud800\\udd51"}')["a"] ==  json.loads('{"a":
>>> json.dumps(json.loads('{"a": "\ud800\udd51"}')["a"])
>>> json.dumps(json.loads('{"a": "\\ud800\\udd51"}')["a"])

Here's Node.js / V8 for comparison:

~$ node --version
~$ node
> JSON.parse('{"a": "\ud800\udd51"}')["a"] ==  JSON.parse('{"a":
> JSON.stringify(JSON.parse('{"a": "\ud800\udd51"}')["a"])
> JSON.stringify(JSON.parse('{"a": "\\ud800\\udd51"}')["a"])

> There is only a single place where the UTF-16 legacy of JavaScript shines
> through in JSON today:
>    To escape an extended character that is not in the Basic Multilingual
>    Plane, the character is represented as a twelve-character sequence,
>    encoding the UTF-16 surrogate pair.  So, for example, a string
>    containing only the G clef character (U+1D11E) may be represented as
>    "\uD834\uDD1E".
> And that is OK because it is just a slightly weird representation of the
> character.
> > > (It is not aligned with JSON's main purpose.)
> >
> > I am not sure what the rationale for that statement is.
> The first sentence of RFC 4627:

I don't find that convincing at all. It is obvious that strings in JSON are
meant to encode all JavaScript strings, as if they were passed to
JavaScript's eval function (there is one unrelated bug here). RFC 4627 even
refers to JSON as a JavaScript subset, and references the eval function in
the security considerations.

If we must "improve" the current text, I have a suggested addition which
borrows from your emails. I'm not sure where to add it, because it doesn't
fit well with the current structure of the document.

"At their most basic level, JSON strings represent a vector of
unconstrained 16-bit values which largely map to UCS-2. Implementations MAY
apply more stringent Unicode validation."

- Rob