Index: autocompleteusers/autocompleteusers.py
===================================================================
--- autocompleteusers/autocompleteusers.py	(revision 16060)
+++ autocompleteusers/autocompleteusers.py	(working copy)
@@ -8,6 +8,7 @@
 
 from trac.config import ListOption
 from trac.core import Component, implements
+from trac.util.presentation import to_json
 from trac.util.text import obfuscate_email_address
 from trac.web.api import IRequestFilter, IRequestHandler
 from trac.web.chrome import Chrome, ITemplateProvider
@@ -36,21 +37,23 @@
         return req.path_info.rstrip('/') == '/subjects'
 
     def process_request(self, req):
+        subjects = []
 
-        subjects = []
         if req.args.get('users', '1') == '1':
-            users = self._get_users(req)
-            subjects = ['%s|%s|%s' % (user[USER],
-                                      user[EMAIL] and '<%s> ' % user[EMAIL] or '',
-                                      user[NAME])
-                        for value, user in users]  # value unused (placeholder needed for sorting)
+            # value unused (placeholder needed for sorting)
+            subjects.extend((user[USER],
+                             user[EMAIL] and '<%s> ' % user[EMAIL] or '',
+                             user[NAME])
+                            for value, user in self._get_users(req))
 
         if req.args.get('groups'):
-            groups = self._get_groups(req)
-            if groups:
-                subjects.extend(['%s||group' % group for group in groups])
+            subjects.extend((group, '', 'group')
+                            for group in self._get_groups(req))
 
-        req.send('\n'.join(subjects).encode('utf-8'), 'text/plain')
+        content = to_json(subjects)
+        if isinstance(content, unicode):
+            content = content.encode('utf-8')
+        req.send(content, 'application/json')
 
     # ITemplateProvider methods
 
Index: autocompleteusers/htdocs/js/autocomplete.js
===================================================================
--- autocompleteusers/htdocs/js/autocomplete.js	(revision 16059)
+++ autocompleteusers/htdocs/js/autocomplete.js	(working copy)
@@ -378,17 +378,14 @@
 
     function parse(data) {
       var parsed = [];
-      var rows = data.split("\n");
+      var rows = data;
       for (var i = 0; i < rows.length; i++) {
-        var row = $.trim(rows[i]);
-        if (row) {
-          row = row.split("|");
-          parsed[parsed.length] = {
-            data: row,
-            value: row[0],
-            result: options.formatResult && options.formatResult(row, row[0]) || row[0]
-          };
-        }
+        var row = rows[i];
+        parsed[i] = {
+          data: row,
+          value: row[0],
+          result: options.formatResult && options.formatResult(row, row[0]) || row[0]
+        };
       }
       return parsed;
     };
Index: tests/test_autocompleteusers.py
===================================================================
--- tests/test_autocompleteusers.py	(revision 16060)
+++ tests/test_autocompleteusers.py	(working copy)
@@ -5,6 +5,7 @@
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution.
 
+import json
 from cStringIO import StringIO
 
 from trac.test import EnvironmentStub, MockPerm
@@ -69,41 +70,45 @@
             self.mod.process_request(req)
             raise AssertionError('not raising RequestDone')
         except RequestDone:
-            return req.response_sent.getvalue().decode('utf-8')
+            return json.loads(req.response_sent.getvalue())
 
     def test_no_users(self):
         req = self._make_req(args={'users': '1'})
-        assert '' == self._process_request(req)
+        assert [] == self._process_request(req)
 
     def test_users(self):
         self._insert_test_users()
         req = self._make_req(args={'users': '1'})
+        assert self._process_request(req) == [
+            ['alice', '<alice@example.org> ', u'Alïcé'],
+            ['bob', '', u'Böb'],
+            ['charlie', '<charlie@example.org> ', ''],
+        ]
+        req = self._make_req(args={'users': '1', 'q': 'cH'})
         assert self._process_request(req) == \
-            u'alice|<alice@example.org> |Alïcé\n' \
-            u'bob||Böb\n' \
-            u'charlie|<charlie@example.org> |'
-        req = self._make_req(args={'users': '1', 'q': 'cH'})
-        assert self._process_request(req) == u'charlie|<charlie@example.org> |'
+            [['charlie', '<charlie@example.org> ', '']]
 
     def test_users_without_email_view(self):
         self._insert_test_users()
         req = self._make_req(args={'users': '1'})
         req.perm = {}  # no permissions
-        assert self._process_request(req) == \
-            u'alice|<alice@…> |Alïcé\n' \
-            u'bob||Böb\n' \
-            u'charlie|<charlie@…> |'
+        assert self._process_request(req) == [
+            ['alice', u'<alice@…> ', u'Alïcé'],
+            ['bob', '', u'Böb'],
+            ['charlie', u'<charlie@…> ', ''],
+        ]
         req = self._make_req(args={'users': '1', 'q': 'B'})
-        assert self._process_request(req) == u'bob||Böb'
+        assert self._process_request(req) == [['bob', '', u'Böb']]
 
     def test_users_with_groups(self):
         self._insert_test_users()
         req = self._make_req(args={'users': '1', 'groups': '1'})
-        assert self._process_request(req) == \
-            u'alice|<alice@example.org> |Alïcé\n' \
-            u'bob||Böb\n' \
-            u'charlie|<charlie@example.org> |\n' \
-            u'anonymous||group\n' \
-            u'authenticated||group'
+        assert self._process_request(req) == [
+            ['alice', '<alice@example.org> ', u'Alïcé'],
+            ['bob', '', u'Böb'],
+            ['charlie', '<charlie@example.org> ', ''],
+            ['anonymous', '', 'group'],
+            ['authenticated', '', 'group'],
+        ]
         req = self._make_req(args={'users': '1', 'groups': '1', 'q': 'An'})
-        assert self._process_request(req) == u'anonymous||group'
+        assert self._process_request(req) == [['anonymous', '', 'group']]
