Changeset: 9ebd128754e3 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/9ebd128754e3
Modified Files:
        monetdb5/modules/atoms/json.c
Branch: default
Log Message:

Handle duplicate keys in JSON object parsing

According to the ECMAscript language specification
(https://262.ecma-international.org/14.0/#sec-internalizejsonproperty)

"In the case where there are duplicate name Strings within an object,
lexically preceding values for the same key shall be overwritten."


diffs (54 lines):

diff --git a/monetdb5/modules/atoms/json.c b/monetdb5/modules/atoms/json.c
--- a/monetdb5/modules/atoms/json.c
+++ b/monetdb5/modules/atoms/json.c
@@ -1058,6 +1058,7 @@ JSONtoken(JSON *jt, const char *j, const
        str msg;
        int nxt, idx = JSONnew(jt);
        const char *string_start = j;
+       int pidx;
 
        if (jt->error)
                return idx;
@@ -1095,12 +1096,36 @@ JSONtoken(JSON *jt, const char *j, const
                        int chld = JSONtoken(jt, j, next);
                        if (jt->error)
                                return idx;
-                       jt->elm[nxt].child = chld;
-                       jt->elm[nxt].value++;
-                       jt->elm[nxt].valuelen -= 2;
-                       JSONappend(jt, idx, nxt);
-                       if (jt->error)
-                               return idx;
+
+                       /* Search for a duplicate key */
+                       for(pidx = nxt - 1; pidx > idx; pidx--) {
+                               if (jt->elm[pidx].kind == JSON_ELEMENT &&
+                                       jt->elm[pidx].valuelen == 
jt->elm[nxt].valuelen - 2 &&
+                                       strncmp(jt->elm[pidx].value, 
jt->elm[nxt].value + 1,
+                                                       jt->elm[nxt].valuelen) 
== 0) {
+                                       break;
+                               }
+                       }
+
+                       /* Duplicate found: Change the value of the previous 
key. */
+                       if (pidx > idx) {
+                               jt->elm[pidx].child = chld;
+                               /* Note that we do not call JSONappend here.
+                                *
+                                * Normally we would de-allocate the old child 
value and the new key,
+                                * but since we are using an arena provided by 
JSONnew, we don't need to.
+                                * This might get expensive for big objects 
with lagre values for
+                                * repeated keys.
+                                */
+
+                       } else {
+                               jt->elm[nxt].child = chld;
+                               jt->elm[nxt].value++;
+                               jt->elm[nxt].valuelen -= 2;
+                               JSONappend(jt, idx, nxt);
+                               if (jt->error)
+                                       return idx;
+                       }
                        j = *next;
                        skipblancs(j);
                        if (*j == '}')
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to