From nobody Tue Feb 10 23:55:37 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1498568134949245.25711086651836; Tue, 27 Jun 2017 05:55:34 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8CB003DBE9; Tue, 27 Jun 2017 12:55:30 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 62976843A9; Tue, 27 Jun 2017 12:55:30 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 131361853E31; Tue, 27 Jun 2017 12:55:30 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v5RClEaJ023835 for ; Tue, 27 Jun 2017 08:47:14 -0400 Received: by smtp.corp.redhat.com (Postfix) id 362AD8A784; Tue, 27 Jun 2017 12:47:14 +0000 (UTC) Received: from andariel.redhat.com (ovpn-204-24.brq.redhat.com [10.40.204.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id B87338A788; Tue, 27 Jun 2017 12:47:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 8CB003DBE9 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=libvir-list-bounces@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 8CB003DBE9 From: Peter Krempa To: libvir-list@redhat.com Date: Tue, 27 Jun 2017 14:46:47 +0200 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Cc: Peter Krempa Subject: [libvirt] [PATCH 6/9] util: json: Properly implement JSON deflattening X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Tue, 27 Jun 2017 12:55:31 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" As it turns out sometimes users pass in an arbitrarily nested structure e.g. for the qemu backing chains JSON pseudo protocol. This new implementation deflatens now a single object fully even with nested keys. Additionally it's not necessary now to stick with the "file." prefix for the properties. Reviewed-by: John Ferlan --- src/util/virjson.c | 67 ++++++++++++++++--= ---- tests/virjsondata/deflatten-basic-generic-out.json | 20 +++++++ .../deflatten-concat-double-key-out.json | 9 --- tests/virjsondata/deflatten-concat-out.json | 7 +-- tests/virjsondata/deflatten-deep-file-out.json | 24 ++++++-- tests/virjsondata/deflatten-deep-generic-out.json | 27 +++++++++ tests/virjsondata/deflatten-double-key-out.json | 6 -- tests/virjsontest.c | 8 +-- 8 files changed, 121 insertions(+), 47 deletions(-) create mode 100644 tests/virjsondata/deflatten-basic-generic-out.json delete mode 100644 tests/virjsondata/deflatten-concat-double-key-out.json create mode 100644 tests/virjsondata/deflatten-deep-generic-out.json delete mode 100644 tests/virjsondata/deflatten-double-key-out.json diff --git a/src/util/virjson.c b/src/util/virjson.c index a8e28cd1b..635b78e3a 100644 --- a/src/util/virjson.c +++ b/src/util/virjson.c @@ -1974,23 +1974,60 @@ virJSONValueObjectDeflattenWorker(const char *key, { virJSONValuePtr retobj =3D opaque; virJSONValuePtr newval =3D NULL; - const char *newkey; + virJSONValuePtr existobj; + char **tokens =3D NULL; + size_t ntokens =3D 0; + int ret =3D -1; - if (!(newkey =3D STRSKIP(key, "file."))) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("JSON object is neither nested nor flattened")); - return -1; + /* non-nested keys only need to be copied */ + if (!strchr(key, '.')) { + if (!(newval =3D virJSONValueCopy(value))) + return -1; + + if (virJSONValueObjectHasKey(retobj, key)) { + virReportError(VIR_ERR_INVALID_ARG, + _("can't deflatten colliding key '%s'"), key); + goto cleanup; + } + + if (virJSONValueObjectAppend(retobj, key, newval) < 0) + goto cleanup; + + return 0; } - if (!(newval =3D virJSONValueCopy(value))) - return -1; + if (!(tokens =3D virStringSplitCount(key, ".", 2, &ntokens))) + goto cleanup; - if (virJSONValueObjectAppend(retobj, newkey, newval) < 0) { - virJSONValueFree(newval); - return -1; + if (ntokens !=3D 2) { + virReportError(VIR_ERR_INVALID_ARG, + _("invalid nested value key '%s'"), key); + goto cleanup; } - return 0; + if (!(existobj =3D virJSONValueObjectGet(retobj, tokens[0]))) { + if (!(existobj =3D virJSONValueNewObject())) + goto cleanup; + + if (virJSONValueObjectAppend(retobj, tokens[0], existobj) < 0) + goto cleanup; + + } else { + if (!virJSONValueIsObject(existobj)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("mixing nested objects and values is forbidde= n in " + "JSON deflattening")); + goto cleanup; + } + } + + ret =3D virJSONValueObjectDeflattenWorker(tokens[1], value, existobj); + + cleanup: + virStringListFreeCount(tokens, ntokens); + virJSONValueFree(newval); + + return ret; } @@ -2005,9 +2042,6 @@ virJSONValueObjectDeflattenWorker(const char *key, * This function will attempt to reverse the process and provide a nested = json * hierarchy so that the parsers can be kept simple and we still can use t= he * weird syntax some users might use. - * - * Currently this function will flatten out just the 'file.' prefix into a= new - * tree. Any other syntax will be rejected. */ virJSONValuePtr virJSONValueObjectDeflatten(virJSONValuePtr json) @@ -2023,10 +2057,7 @@ virJSONValueObjectDeflatten(virJSONValuePtr json) deflattened) < 0) goto cleanup; - if (virJSONValueObjectCreate(&ret, "a:file", deflattened, NULL) < 0) - goto cleanup; - - deflattened =3D NULL; + VIR_STEAL_PTR(ret, deflattened); cleanup: virJSONValueFree(deflattened); diff --git a/tests/virjsondata/deflatten-basic-generic-out.json b/tests/vir= jsondata/deflatten-basic-generic-out.json new file mode 100644 index 000000000..ab639aa48 --- /dev/null +++ b/tests/virjsondata/deflatten-basic-generic-out.json @@ -0,0 +1,20 @@ +{ + "foo": { + "int": 1, + "string": "string", + "object": { + "data": "value", + "foo": "bar" + } + }, + "bar": { + "int": 1 + }, + "blurb": { + "string": "string", + "object": { + "data": "value", + "foo": "bar" + } + } +} diff --git a/tests/virjsondata/deflatten-concat-double-key-out.json b/tests= /virjsondata/deflatten-concat-double-key-out.json deleted file mode 100644 index 5624ef123..000000000 --- a/tests/virjsondata/deflatten-concat-double-key-out.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "file": { - "nest": { - "into": "is already here" - }, - "nest.into": 2, - "nest.there": "too" - } -} diff --git a/tests/virjsondata/deflatten-concat-out.json b/tests/virjsondat= a/deflatten-concat-out.json index 539d2cc30..be417e53a 100644 --- a/tests/virjsondata/deflatten-concat-out.json +++ b/tests/virjsondata/deflatten-concat-out.json @@ -1,9 +1,8 @@ { "file": { "nest": { - - }, - "nest.into": 2, - "nest.there": "too" + "into": 2, + "there": "too" + } } } diff --git a/tests/virjsondata/deflatten-deep-file-out.json b/tests/virjson= data/deflatten-deep-file-out.json index a5910c9f7..d4614eeaf 100644 --- a/tests/virjsondata/deflatten-deep-file-out.json +++ b/tests/virjsondata/deflatten-deep-file-out.json @@ -1,11 +1,23 @@ { "file": { - "double.nest1": "some", - "double.nest2": "more", - "double.nest3": { - "even": "objects" + "double": { + "nest1": "some", + "nest2": "more", + "nest3": { + "even": "objects" + } }, - "very.deeply.nested.object.chains.nest1": "some", - "very.deeply.nested.object.chains.nest2": "stuff" + "very": { + "deeply": { + "nested": { + "object": { + "chains": { + "nest1": "some", + "nest2": "stuff" + } + } + } + } + } } } diff --git a/tests/virjsondata/deflatten-deep-generic-out.json b/tests/virj= sondata/deflatten-deep-generic-out.json new file mode 100644 index 000000000..7ea521a8f --- /dev/null +++ b/tests/virjsondata/deflatten-deep-generic-out.json @@ -0,0 +1,27 @@ +{ + "foo": { + "double": { + "nest1": "some", + "nest2": "more" + }, + "very": { + "deeply": { + "nested": { + "object": { + "chains": { + "nest1": "some", + "nest2": "stuff" + } + } + } + } + } + }, + "bar": { + "double": { + "nest3": { + "even": "objects" + } + } + } +} diff --git a/tests/virjsondata/deflatten-double-key-out.json b/tests/virjso= ndata/deflatten-double-key-out.json deleted file mode 100644 index ca6766e5b..000000000 --- a/tests/virjsondata/deflatten-double-key-out.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "file": { - "nest": 1, - "nest.into": 2 - } -} diff --git a/tests/virjsontest.c b/tests/virjsontest.c index d69b22bf3..b3ce6591a 100644 --- a/tests/virjsontest.c +++ b/tests/virjsontest.c @@ -514,13 +514,13 @@ mymain(void) DO_TEST_DEFLATTEN("unflattened", true); DO_TEST_DEFLATTEN("basic-file", true); - DO_TEST_DEFLATTEN("basic-generic", false); + DO_TEST_DEFLATTEN("basic-generic", true); DO_TEST_DEFLATTEN("deep-file", true); - DO_TEST_DEFLATTEN("deep-generic", false); + DO_TEST_DEFLATTEN("deep-generic", true); DO_TEST_DEFLATTEN("nested", true); - DO_TEST_DEFLATTEN("double-key", true); + DO_TEST_DEFLATTEN("double-key", false); DO_TEST_DEFLATTEN("concat", true); - DO_TEST_DEFLATTEN("concat-double-key", true); + DO_TEST_DEFLATTEN("concat-double-key", false); return (ret =3D=3D 0) ? EXIT_SUCCESS : EXIT_FAILURE; } --=20 2.12.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list