From ed8ec8f092cadb94e5ebb4fdcdaf3102074ee31a Mon Sep 17 00:00:00 2001
From: Torsten Dreyer <torsten@t3r.de>
Date: Fri, 7 Mar 2014 21:53:51 +0100
Subject: [PATCH] JSON: make the response configurable, set encoding

add request parameter 'i' and 'd'
if i=y, indent the output to make it human readable
if i is missing or anything else, send the output unformatted to save bandwith

'd' defines recursion depth with a default of 1 to show the requested node
and the immediate childs (if it has any)

call /json/?i=y&d=999 for a complete property tree backup (use with caution!)

Also set the encoding to UTF-8 as required per RFC 4627
---
 src/Network/http/JsonUriHandler.cxx | 40 +++++++++++++++++------------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/src/Network/http/JsonUriHandler.cxx b/src/Network/http/JsonUriHandler.cxx
index 3c67e8546..22e18d0ba 100644
--- a/src/Network/http/JsonUriHandler.cxx
+++ b/src/Network/http/JsonUriHandler.cxx
@@ -48,19 +48,26 @@ static const char * getPropertyTypeString( simgear::props::Type type )
   }
 }
 
-static cJSON * PropToJson( SGPropertyNode_ptr n )
+static cJSON * PropToJson( SGPropertyNode_ptr n, int depth )
 {
-  cJSON * jsonProp = cJSON_CreateObject();
-  cJSON_AddItemToObject(jsonProp, "path", cJSON_CreateString(n->getPath(true).c_str()));
-  cJSON_AddItemToObject(jsonProp, "name", cJSON_CreateString(n->getName()));
-  cJSON_AddItemToObject(jsonProp, "value", cJSON_CreateString(n->getStringValue()));
-  cJSON_AddItemToObject(jsonProp, "type", cJSON_CreateString(getPropertyTypeString(n->getType())));
-  return jsonProp;
+  cJSON * json = cJSON_CreateObject();
+  cJSON_AddItemToObject(json, "path", cJSON_CreateString(n->getPath(true).c_str()));
+  cJSON_AddItemToObject(json, "name", cJSON_CreateString(n->getName()));
+  cJSON_AddItemToObject(json, "value", cJSON_CreateString(n->getStringValue()));
+  cJSON_AddItemToObject(json, "type", cJSON_CreateString(getPropertyTypeString(n->getType())));
+
+  if( depth > 0 && n->nChildren() > 0 ) {
+    cJSON * jsonArray = cJSON_CreateArray();
+    for( int i = 0; i < n->nChildren(); i++ )
+      cJSON_AddItemToArray( jsonArray, PropToJson( n->getChild(i), depth-1 ) );
+    cJSON_AddItemToObject( json, "children", jsonArray );
+  }
+  return json;
 }
 
 bool JsonUriHandler::handleGetRequest( const HTTPRequest & request, HTTPResponse & response )
 {
-  response.Header["Content-Type"] = "application/json; charset=ISO-8859-1";
+  response.Header["Content-Type"] = "application/json; charset=UTF-8";
 
   string propertyPath = request.Uri;
 
@@ -77,6 +84,13 @@ bool JsonUriHandler::handleGetRequest( const HTTPRequest & request, HTTPResponse
   while( false == propertyPath.empty() && propertyPath[ propertyPath.length()-1 ] == '/' )
     propertyPath = propertyPath.substr(0,propertyPath.length()-1);
 
+  // max recursion depth
+  int  depth = atoi(request.RequestVariables.get("d").c_str());
+  if( depth < 1 ) depth = 1; // at least one level 
+
+  // pretty print (y) or compact print (default)
+  bool indent = request.RequestVariables.get("i") == "y";
+
   SGPropertyNode_ptr node = fgGetNode( string("/") + propertyPath );
   if( false == node.valid() ) {
     response.StatusCode = 400;
@@ -86,15 +100,9 @@ bool JsonUriHandler::handleGetRequest( const HTTPRequest & request, HTTPResponse
 
   } 
 
-  cJSON * json = PropToJson( node );
-  if( node->nChildren() > 0 ) {
-    cJSON * jsonArray = cJSON_CreateArray();
-    for( int i = 0; i < node->nChildren(); i++ )
-      cJSON_AddItemToArray( jsonArray, PropToJson( node->getChild(i) ) );
-    cJSON_AddItemToObject( json, "children", jsonArray );
-  }
+  cJSON * json = PropToJson( node, depth );
 
-  char * jsonString = cJSON_Print( json );
+  char * jsonString = indent ? cJSON_Print( json ) : cJSON_PrintUnformatted( json );
   response.Content = jsonString;
   free( jsonString );
   cJSON_Delete( json );