Index: /trunk/src/org/openstreetmap/josm/io/remotecontrol/RequestProcessor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/remotecontrol/RequestProcessor.java	(revision 16549)
+++ /trunk/src/org/openstreetmap/josm/io/remotecontrol/RequestProcessor.java	(revision 16550)
@@ -7,10 +7,10 @@
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.StringWriter;
 import java.io.Writer;
 import java.net.Socket;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
@@ -24,4 +24,11 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
 
 import org.openstreetmap.josm.gui.help.HelpUtil;
@@ -390,23 +397,14 @@
 
     /**
-     * Returns the JSON information for all handlers.
-     * @return the JSON information for all handlers
-     */
-    public static String getHandlersInfoAsJSON() {
-        StringBuilder r = new StringBuilder();
-        boolean first = true;
-        r.append('[');
-
-        for (Entry<String, Class<? extends RequestHandler>> p : handlers.entrySet()) {
-            if (first) {
-                first = false;
-            } else {
-                r.append(", ");
-            }
-            r.append(getHandlerInfoAsJSON(p.getKey()));
-        }
-        r.append(']');
-
-        return r.toString();
+     * Returns the JSON information for the given (if null: all) handlers.
+     * @param handlers the handlers
+     * @return the JSON information for the given (if null: all) handlers
+     */
+    public static JsonArray getHandlersInfoAsJSON(Collection<String> handlers) {
+        JsonArrayBuilder json = Json.createArrayBuilder();
+        for (String s : Utils.firstNonNull(handlers, RequestProcessor.handlers.keySet())) {
+            json.add(getHandlerInfoAsJSON(s));
+        }
+        return json.build();
     }
 
@@ -416,70 +414,34 @@
      * @return JSON information for the given handler
      */
-    public static String getHandlerInfoAsJSON(String cmd) {
-        try (StringWriter w = new StringWriter()) {
-            RequestHandler handler = null;
-            try {
-                Class<?> c = handlers.get(cmd);
-                if (c == null) return null;
-                handler = handlers.get(cmd).getConstructor().newInstance();
-            } catch (ReflectiveOperationException ex) {
-                Logging.error(ex);
-                return null;
-            }
-
-            try (PrintWriter r = new PrintWriter(w)) {
-                printJsonInfo(cmd, r, handler);
-                return w.toString();
-            }
-        } catch (IOException e) {
-            Logging.error(e);
+    public static JsonObject getHandlerInfoAsJSON(String cmd) {
+        RequestHandler handler;
+        try {
+            Class<?> c = handlers.get(cmd);
+            if (c == null) return null;
+            handler = handlers.get(cmd).getConstructor().newInstance();
+        } catch (ReflectiveOperationException ex) {
+            Logging.warn("Unknown handler " + cmd);
+            Logging.error(ex);
             return null;
         }
-    }
-
-    private static void printJsonInfo(String cmd, PrintWriter r, RequestHandler handler) {
-        r.printf("{ \"request\" : \"%s\"", cmd);
+        return getHandlerInfoAsJSON(cmd, handler);
+    }
+
+    private static JsonObject getHandlerInfoAsJSON(String cmd, RequestHandler handler) {
+        JsonObjectBuilder json = Json.createObjectBuilder();
+        json.add("request", cmd);
         if (handler.getUsage() != null) {
-            r.printf(", \"usage\" : \"%s\"", handler.getUsage());
-        }
-        r.append(", \"parameters\" : [");
-
-        String[] params = handler.getMandatoryParams();
-        if (params != null) {
-            for (int i = 0; i < params.length; i++) {
-                if (i == 0) {
-                    r.append('\"');
-                } else {
-                    r.append(", \"");
-                }
-                r.append(params[i]).append('\"');
-            }
-        }
-        r.append("], \"optional\" : [");
-        String[] optional = handler.getOptionalParams();
-        if (optional != null) {
-            for (int i = 0; i < optional.length; i++) {
-                if (i == 0) {
-                    r.append('\"');
-                } else {
-                    r.append(", \"");
-                }
-                r.append(optional[i]).append('\"');
-            }
-        }
-
-        r.append("], \"examples\" : [");
-        String[] examples = handler.getUsageExamples(cmd.substring(1));
-        if (examples != null) {
-            for (int i = 0; i < examples.length; i++) {
-                if (i == 0) {
-                    r.append('\"');
-                } else {
-                    r.append(", \"");
-                }
-                r.append(examples[i]).append('\"');
-            }
-        }
-        r.append("]}");
+            json.add("usage", handler.getUsage());
+        }
+        json.add("parameters", toJsonArray(handler.getMandatoryParams()));
+        json.add("optional", toJsonArray(handler.getOptionalParams()));
+        json.add("examples", toJsonArray(handler.getUsageExamples(cmd.substring(1))));
+        return json.build();
+    }
+
+    private static JsonArray toJsonArray(String[] strings) {
+        return Arrays.stream(strings)
+                .collect(Collectors.collectingAndThen(Collectors.toList(), Json::createArrayBuilder))
+                .build();
     }
 
Index: /trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/FeaturesHandler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/FeaturesHandler.java	(revision 16549)
+++ /trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/FeaturesHandler.java	(revision 16550)
@@ -4,7 +4,9 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.util.Arrays;
+import java.util.Collection;
+
 import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
 import org.openstreetmap.josm.io.remotecontrol.RequestProcessor;
-import org.openstreetmap.josm.tools.Logging;
 
 /**
@@ -20,30 +22,8 @@
 
     @Override
-    protected void handleRequest() throws RequestHandlerErrorException,
-            RequestHandlerBadRequestException {
-        StringBuilder buf = new StringBuilder();
+    protected void handleRequest() throws RequestHandlerErrorException, RequestHandlerBadRequestException {
         String q = args.get("q");
-        if (q != null) {
-            buf.append('[');
-            boolean first = true;
-            for (String s: q.split("[,\\s]+")) {
-               if (first) {
-                   first = false;
-               } else {
-                   buf.append(", ");
-               }
-               String info = RequestProcessor.getHandlerInfoAsJSON('/'+s);
-               if (info != null) {
-                   buf.append(info);
-               } else {
-                   Logging.warn("Unknown handler {0} passed to /features request", s);
-               }
-            }
-            buf.append(']');
-        } else {
-            buf.append(RequestProcessor.getHandlersInfoAsJSON());
-        }
-
-        content = buf.toString();
+        Collection<String> handlers = q == null ? null : Arrays.asList(q.split("[,\\s]+"));
+        content = RequestProcessor.getHandlersInfoAsJSON(handlers).toString();
         contentType = "application/json";
         if (args.containsKey("jsonp")) {
