Selaa lähdekoodia

HPCC-9085 Fix Roxie JSON handling of array item names

Simple arrays (ECL Sets) will no longer output names for items in
the array.  Also nested children with same name as array ancestor
will not be treated as array items.

Signed-off-by: Anthony Fishbeck <Anthony.Fishbeck@lexisnexis.com>
Anthony Fishbeck 12 vuotta sitten
vanhempi
commit
64e2e61c16
2 muutettua tiedostoa jossa 71 lisäystä ja 30 poistoa
  1. 55 28
      common/thorhelper/thorxmlwrite.cpp
  2. 16 2
      common/thorhelper/thorxmlwrite.hpp

+ 55 - 28
common/thorhelper/thorxmlwrite.cpp

@@ -351,6 +351,36 @@ void CommonJsonWriter::checkDelimit(int inc)
     checkFormat(true, true, inc);
 }
 
+const char *CommonJsonWriter::checkItemName(CJsonWriterItem *item, const char *name)
+{
+    if (item && item->depth==0 && strieq(item->name, name))
+        return NULL;
+    return name;
+}
+
+const char *CommonJsonWriter::checkItemName(const char *name)
+{
+    CJsonWriterItem *item = (arrays.length()) ? &arrays.tos() : NULL;
+    return checkItemName(item, name);
+}
+
+const char *CommonJsonWriter::checkItemNameInc(const char *name)
+{
+    CJsonWriterItem *item = (arrays.length()) ? &arrays.tos() : NULL;
+    name = checkItemName(item, name);
+    if (item)
+        item->depth++;
+    return name;
+}
+
+const char *CommonJsonWriter::checkItemNameDec(const char *name)
+{
+    CJsonWriterItem *item = (arrays.length()) ? &arrays.tos() : NULL;
+    if (item)
+        item->depth--;
+    return checkItemName(item, name);
+}
+
 void CommonJsonWriter::outputQuoted(const char *text)
 {
     checkDelimit();
@@ -364,7 +394,7 @@ void CommonJsonWriter::outputString(unsigned len, const char *field, const char
     if ((flags & XWFopt) && (rtlTrimStrLen(len, field) == 0))
         return;
     checkDelimit();
-    appendJSONValue(out, fieldname, len, field);
+    appendJSONValue(out, checkItemName(fieldname), len, field);
 }
 
 void CommonJsonWriter::outputQString(unsigned len, const char *field, const char *fieldname)
@@ -382,43 +412,43 @@ void CommonJsonWriter::outputQString(unsigned len, const char *field, const char
 void CommonJsonWriter::outputBool(bool field, const char *fieldname)
 {
     checkDelimit();
-    appendJSONValue(out, fieldname, field);
+    appendJSONValue(out, checkItemName(fieldname), field);
 }
 
 void CommonJsonWriter::outputData(unsigned len, const void *field, const char *fieldname)
 {
     checkDelimit();
-    appendJSONValue(out, fieldname, len, field);
+    appendJSONValue(out, checkItemName(fieldname), len, field);
 }
 
 void CommonJsonWriter::outputInt(__int64 field, const char *fieldname)
 {
     checkDelimit();
-    appendJSONValue(out, fieldname, field);
+    appendJSONValue(out, checkItemName(fieldname), field);
 }
 
 void CommonJsonWriter::outputUInt(unsigned __int64 field, const char *fieldname)
 {
     checkDelimit();
-    appendJSONValue(out, fieldname, field);
+    appendJSONValue(out, checkItemName(fieldname), field);
 }
 
 void CommonJsonWriter::outputReal(double field, const char *fieldname)
 {
     checkDelimit();
-    appendJSONValue(out, fieldname, field);
+    appendJSONValue(out, checkItemName(fieldname), field);
 }
 
 void CommonJsonWriter::outputDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
 {
     checkDelimit();
-    outputJsonDecimal(field, size, precision, fieldname, out);
+    outputJsonDecimal(field, size, precision, checkItemName(fieldname), out);
 }
 
 void CommonJsonWriter::outputUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
 {
     checkDelimit();
-    outputJsonUDecimal(field, size, precision, fieldname, out);
+    outputJsonUDecimal(field, size, precision, checkItemName(fieldname), out);
 }
 
 void CommonJsonWriter::outputUnicode(unsigned len, const UChar *field, const char *fieldname)
@@ -428,7 +458,7 @@ void CommonJsonWriter::outputUnicode(unsigned len, const UChar *field, const cha
     if ((flags & XWFopt) && (rtlTrimUnicodeStrLen(len, field) == 0))
         return;
     checkDelimit();
-    outputJsonUnicode(len, field, fieldname, out);
+    outputJsonUnicode(len, field, checkItemName(fieldname), out);
 }
 
 void CommonJsonWriter::outputUtf8(unsigned len, const char *field, const char *fieldname)
@@ -438,12 +468,12 @@ void CommonJsonWriter::outputUtf8(unsigned len, const char *field, const char *f
     if ((flags & XWFopt) && (rtlTrimUtf8StrLen(len, field) == 0))
         return;
     checkDelimit();
-    appendJSONValue(out, fieldname, len, field);
+    appendJSONValue(out, checkItemName(fieldname), len, field);
 }
 
 void CommonJsonWriter::outputBeginArray(const char *fieldname)
 {
-    arrays.append(fieldname);
+    arrays.append(*new CJsonWriterItem(fieldname));
     const char * sep = strchr(fieldname, '/');
     while (sep)
     {
@@ -471,24 +501,21 @@ void CommonJsonWriter::outputEndArray(const char *fieldname)
 
 void CommonJsonWriter::outputBeginNested(const char *fieldname, bool nestChildren)
 {
-    const char *parentArray = (arrays.length()) ? arrays.tos() : NULL;
-    if (parentArray && !streq(parentArray, fieldname))
-        parentArray = NULL;
     flush(false);
     checkFormat(true, false, 1);
-    const char * sep = (fieldname) ? strchr(fieldname, '/') : NULL;
-    while (sep)
+    fieldname = checkItemNameInc(fieldname);
+    if (fieldname)
     {
-        if (!parentArray)
+        const char * sep = (fieldname) ? strchr(fieldname, '/') : NULL;
+        while (sep)
         {
             StringAttr leading(fieldname, sep-fieldname);
             appendJSONName(out, leading).append("{");
+            fieldname = sep+1;
+            sep = strchr(fieldname, '/');
         }
-        fieldname = sep+1;
-        sep = strchr(fieldname, '/');
-    }
-    if (!parentArray)
         appendJSONName(out, fieldname);
+    }
     out.append("{");
     if (!nestChildren && !nestLimit)
         nestLimit = indent;
@@ -496,17 +523,17 @@ void CommonJsonWriter::outputBeginNested(const char *fieldname, bool nestChildre
 
 void CommonJsonWriter::outputEndNested(const char *fieldname)
 {
-    const char *parentArray = (arrays.length()) ? arrays.tos() : NULL;
-    if (parentArray && !streq(parentArray, fieldname))
-        parentArray = NULL;
     flush(false);
     checkFormat(false, true, -1);
-    const char * sep = (fieldname) ? strchr(fieldname, '/') : NULL;
-    while (sep)
+    fieldname = checkItemNameDec(fieldname);
+    if (fieldname)
     {
-        if (!parentArray)
+        const char * sep = (fieldname) ? strchr(fieldname, '/') : NULL;
+        while (sep)
+        {
             out.append('}');
-        sep = strchr(sep+1, '/');
+            sep = strchr(sep+1, '/');
+        }
     }
     out.append("}");
     if (indent==nestLimit)

+ 16 - 2
common/thorhelper/thorxmlwrite.hpp

@@ -122,9 +122,23 @@ protected:
             flusher->flushXML(out, isClose);
     }
 
-protected:
+    class CJsonWriterItem : public CInterface
+    {
+    public:
+        CJsonWriterItem(const char *_name) : name(_name), depth(0){}
+        IMPLEMENT_IINTERFACE;
+
+        StringAttr name;
+        unsigned depth;
+    };
+
+    const char *checkItemName(CJsonWriterItem *item, const char *name);
+    const char *checkItemName(const char *name);
+    const char *checkItemNameInc(const char *name);
+    const char *checkItemNameDec(const char *name);
+
     IXmlStreamFlusher *flusher;
-    StringArray arrays;
+    CIArrayOf<CJsonWriterItem> arrays;
     StringBuffer out;
     unsigned flags;
     unsigned indent;