038951920f067e656d752b8325a4e3a808354cbc
angie
  Wed Jan 7 12:13:37 2015 -0800
Fixed the behavior of jsonStringEscape for \n, \r and \t.  Previously,it was inserting a \ followed by the actual \n / \r / \t character, which
was not actually escaping it.  A \n needs to be replaced by a \ followed by
an n not \n.  Also added jsonOptionalBooleanField.

diff --git src/lib/jsonParse.c src/lib/jsonParse.c
index 3b9d034..ad5f3de 100644
--- src/lib/jsonParse.c
+++ src/lib/jsonParse.c
@@ -298,61 +298,74 @@
 
 if (inString == NULL)
     return(cloneString(""));
 
 /* Count up how long it will be */
 in = inString;
 while ((c = *in++) != 0)
     {
     switch(c)
         {
         case '\"':
         case '\\':
         case '/':
         case '\b':
         case '\f':
-        case '\n':
+            outSize += 2;
+            break;
         case '\r':
         case '\t':
-            outSize += 2;
+        case '\n':
+            outSize += 3;
             break;
         default:
             outSize += 1;
         }
     }
 outString = needMem(outSize+1);
 
 /* Encode string */
 in = inString;
 out = outString;
 while ((c = *in++) != 0)
     {
     switch(c)
         {
         case '\"':
         case '\\':
         case '/':
         case '\b':
         case '\f':
-        case '\n':
+            *out++ = '\\';
+            *out++ = c;
+            break;
         case '\r':
+            *out++ = '\\';
+            *out++ = 'r';
+            break;
         case '\t':
             *out++ = '\\';
+            *out++ = 't';
             break;
-        }
+        case '\n':
+            *out++ = '\\';
+            *out++ = 'n';
+            break;
+        default:
             *out++ = c;
         }
+    }
 *out++ = 0;
 return outString;
 }
 
 void jsonFindNameRecurse(struct jsonElement *ele, char *jName, struct slName **pList)
 // Search the JSON tree recursively to find all the values associated to
 // the name, and add them to head of the list.  
 {
 switch (ele->type)
     {
     case jsonObject:
         {
         if(hashNumEntries(ele->val.jeHash))
             {
             struct hashEl *el, *list = hashElListHash(ele->val.jeHash);
@@ -673,15 +686,23 @@
 struct jsonElement *ele = jsonFindNamedField(object, "", field);
 if (ele == NULL)
      return defaultVal;
 return jsonStringVal(ele, field);
 }
 
 char *jsonStringField(struct jsonElement *object, char *field)
 /* Return string valued field of object or abort if field doesn't exist. */
 {
 char *val = jsonOptionalStringField(object, field, NULL);
 if (val == NULL)
     errAbort("Field %s doesn't exist in json object", field);
 return val;
 }
 
+boolean jsonOptionalBooleanField(struct jsonElement *object, char *field, boolean defaultVal)
+/* Return boolean valued field of object, or defaultVal if it doesn't exist. */
+{
+struct jsonElement *ele = jsonFindNamedField(object, "", field);
+if (ele == NULL)
+     return defaultVal;
+return jsonBooleanVal(ele, field);
+}