Yajl has not seen much activity upstream recently.
Switch to using Jansson >= 2.7.
All the platforms we target on https://libvirt.org/platforms.html
have a version >= 2.7 listed on the sites below:
https://repology.org/metapackage/jansson/versions
https://build.opensuse.org/package/show/devel:libraries:c_c++/libjansson
Implement virJSONValue{From,To}String using Jansson, delete the yajl
code (and the related virJSONParser structure) and report an error
if someone explicitly specifies --with-yajl.
Also adjust the test data to account for Jansson's different whitespace
usage for empty arrays and tune up the specfile to keep 'make rpm'
working when bisecting.
Signed-off-by: Ján Tomko <jtomko@redhat.com>
---
src/util/virjson.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 223 insertions(+)
diff --git a/src/util/virjson.c b/src/util/virjson.c
index 92a15b28a1..cb38c35522 100644
--- a/src/util/virjson.c
+++ b/src/util/virjson.c
@@ -2011,6 +2011,229 @@ virJSONValueToString(virJSONValuePtr object,
}
+#elif WITH_JANSSON
+# include <jansson.h>
+
+static virJSONValuePtr
+virJSONValueFromJansson(json_t *json)
+{
+ virJSONValuePtr ret = NULL;
+ const char *key;
+ json_t *cur;
+ size_t i;
+
+ switch (json_typeof(json)) {
+ case JSON_OBJECT:
+ ret = virJSONValueNewObject();
+ if (!ret)
+ goto error;
+
+ json_object_foreach(json, key, cur) {
+ virJSONValuePtr val = virJSONValueFromJansson(cur);
+ if (!val)
+ goto error;
+
+ if (virJSONValueObjectAppend(ret, key, val) < 0) {
+ virJSONValueFree(val);
+ goto error;
+ }
+ }
+
+ break;
+
+ case JSON_ARRAY:
+ ret = virJSONValueNewArray();
+ if (!ret)
+ goto error;
+
+ json_array_foreach(json, i, cur) {
+ virJSONValuePtr val = virJSONValueFromJansson(cur);
+ if (!val)
+ goto error;
+
+ if (virJSONValueArrayAppend(ret, val) < 0) {
+ virJSONValueFree(val);
+ goto error;
+ }
+ }
+ break;
+
+ case JSON_STRING:
+ ret = virJSONValueNewStringLen(json_string_value(json),
+ json_string_length(json));
+ break;
+
+ case JSON_INTEGER:
+ ret = virJSONValueNewNumberLong(json_integer_value(json));
+ break;
+
+ case JSON_REAL:
+ ret = virJSONValueNewNumberDouble(json_real_value(json));
+ break;
+
+ case JSON_TRUE:
+ case JSON_FALSE:
+ ret = virJSONValueNewBoolean(json_boolean_value(json));
+ break;
+
+ case JSON_NULL:
+ ret = virJSONValueNewNull();
+ break;
+ }
+
+ return ret;
+
+ error:
+ virJSONValueFree(ret);
+ return NULL;
+}
+
+virJSONValuePtr
+virJSONValueFromString(const char *jsonstring)
+{
+ virJSONValuePtr ret = NULL;
+ json_t *json;
+ json_error_t error;
+ size_t flags = JSON_REJECT_DUPLICATES |
+ JSON_DECODE_ANY;
+
+ if (!(json = json_loads(jsonstring, flags, &error))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to parse JSON %d:%d: %s"),
+ error.line, error.column, error.text);
+ return NULL;
+ }
+
+ ret = virJSONValueFromJansson(json);
+ json_decref(json);
+ return ret;
+}
+
+
+static json_t *
+virJSONValueToJansson(virJSONValuePtr object)
+{
+ json_error_t error;
+ json_t *ret = NULL;
+ size_t i;
+
+ switch (object->type) {
+ case VIR_JSON_TYPE_OBJECT:
+ ret = json_object();
+ if (!ret) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to create JSON object: %s"),
+ error.text);
+ goto error;
+ }
+ for (i = 0; i < object->data.object.npairs; i++) {
+ virJSONObjectPairPtr cur = object->data.object.pairs + i;
+ json_t *val = virJSONValueToJansson(cur->value);
+
+ if (!val)
+ goto error;
+ if (json_object_set_new(ret, cur->key, val) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to set JSON object: %s"),
+ error.text);
+ goto error;
+ }
+ }
+ break;
+
+ case VIR_JSON_TYPE_ARRAY:
+ ret = json_array();
+ if (!ret) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to create JSON array: %s"),
+ error.text);
+ goto error;
+ }
+ for (i = 0; i < object->data.array.nvalues; i++) {
+ virJSONValuePtr cur = object->data.array.values[i];
+ json_t *val = virJSONValueToJansson(cur);
+
+ if (!val)
+ goto error;
+ if (json_array_append_new(ret, val) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to append array value: %s"),
+ error.text);
+ goto error;
+ }
+ }
+ break;
+
+ case VIR_JSON_TYPE_STRING:
+ ret = json_string(object->data.string);
+ break;
+
+ case VIR_JSON_TYPE_NUMBER: {
+ long long ll_val;
+ double d_val;
+ if (virStrToLong_ll(object->data.number, NULL, 10, &ll_val) < 0) {
+ if (virStrToDouble(object->data.number, NULL, &d_val) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("JSON value is not a number"));
+ return NULL;
+ }
+ ret = json_real(d_val);
+ } else {
+ ret = json_integer(ll_val);
+ }
+ }
+ break;
+
+ case VIR_JSON_TYPE_BOOLEAN:
+ ret = json_boolean(object->data.boolean);
+ break;
+
+ case VIR_JSON_TYPE_NULL:
+ ret = json_null();
+ break;
+ }
+ if (!ret) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("error creating JSON value: %s"),
+ error.text);
+ }
+ return ret;
+
+ error:
+ json_decref(ret);
+ return NULL;
+}
+
+
+char *
+virJSONValueToString(virJSONValuePtr object,
+ bool pretty)
+{
+ size_t flags = JSON_ENCODE_ANY;
+ json_t *json;
+ json_error_t error;
+ char *str = NULL;
+
+ if (pretty)
+ flags |= JSON_INDENT(2);
+ else
+ flags |= JSON_COMPACT;
+
+ json = virJSONValueToJansson(object);
+ if (!json)
+ return NULL;
+
+ str = json_dumps(json, flags);
+ if (!str) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to format JSON %d:%d: %s"),
+ error.line, error.column, error.text);
+ }
+ json_decref(json);
+ return str;
+}
+
+
#else
virJSONValuePtr
virJSONValueFromString(const char *jsonstring ATTRIBUTE_UNUSED)
--
2.16.1
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On Thu, May 10, 2018 at 18:44:17 +0200, Ján Tomko wrote:
> Yajl has not seen much activity upstream recently.
> Switch to using Jansson >= 2.7.
>
> All the platforms we target on https://libvirt.org/platforms.html
> have a version >= 2.7 listed on the sites below:
> https://repology.org/metapackage/jansson/versions
> https://build.opensuse.org/package/show/devel:libraries:c_c++/libjansson
>
> Implement virJSONValue{From,To}String using Jansson, delete the yajl
> code (and the related virJSONParser structure) and report an error
> if someone explicitly specifies --with-yajl.
>
> Also adjust the test data to account for Jansson's different whitespace
> usage for empty arrays and tune up the specfile to keep 'make rpm'
> working when bisecting.
>
> Signed-off-by: Ján Tomko <jtomko@redhat.com>
> ---
> src/util/virjson.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 223 insertions(+)
>
> diff --git a/src/util/virjson.c b/src/util/virjson.c
> index 92a15b28a1..cb38c35522 100644
> --- a/src/util/virjson.c
> +++ b/src/util/virjson.c
> @@ -2011,6 +2011,229 @@ virJSONValueToString(virJSONValuePtr object,
> }
>
>
> +#elif WITH_JANSSON
> +# include <jansson.h>
> +
> +static virJSONValuePtr
> +virJSONValueFromJansson(json_t *json)
> +{
> + virJSONValuePtr ret = NULL;
> + const char *key;
> + json_t *cur;
> + size_t i;
> +
> + switch (json_typeof(json)) {
> + case JSON_OBJECT:
> + ret = virJSONValueNewObject();
> + if (!ret)
> + goto error;
> +
> + json_object_foreach(json, key, cur) {
> + virJSONValuePtr val = virJSONValueFromJansson(cur);
> + if (!val)
> + goto error;
> +
> + if (virJSONValueObjectAppend(ret, key, val) < 0) {
> + virJSONValueFree(val);
> + goto error;
> + }
> + }
> +
> + break;
> +
> + case JSON_ARRAY:
> + ret = virJSONValueNewArray();
> + if (!ret)
> + goto error;
> +
> + json_array_foreach(json, i, cur) {
> + virJSONValuePtr val = virJSONValueFromJansson(cur);
> + if (!val)
> + goto error;
> +
> + if (virJSONValueArrayAppend(ret, val) < 0) {
> + virJSONValueFree(val);
> + goto error;
> + }
> + }
> + break;
> +
> + case JSON_STRING:
> + ret = virJSONValueNewStringLen(json_string_value(json),
> + json_string_length(json));
> + break;
> +
> + case JSON_INTEGER:
> + ret = virJSONValueNewNumberLong(json_integer_value(json));
> + break;
> +
> + case JSON_REAL:
> + ret = virJSONValueNewNumberDouble(json_real_value(json));
> + break;
> +
> + case JSON_TRUE:
> + case JSON_FALSE:
> + ret = virJSONValueNewBoolean(json_boolean_value(json));
> + break;
> +
> + case JSON_NULL:
> + ret = virJSONValueNewNull();
> + break;
Maybe add a 'default' case?
> + }
> +
> + return ret;
> +
> + error:
> + virJSONValueFree(ret);
> + return NULL;
> +}
> +
> +virJSONValuePtr
> +virJSONValueFromString(const char *jsonstring)
> +{
> + virJSONValuePtr ret = NULL;
> + json_t *json;
> + json_error_t error;
> + size_t flags = JSON_REJECT_DUPLICATES |
> + JSON_DECODE_ANY;
> +
> + if (!(json = json_loads(jsonstring, flags, &error))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("failed to parse JSON %d:%d: %s"),
> + error.line, error.column, error.text);
> + return NULL;
> + }
> +
> + ret = virJSONValueFromJansson(json);
> + json_decref(json);
> + return ret;
> +}
> +
> +
> +static json_t *
> +virJSONValueToJansson(virJSONValuePtr object)
> +{
> + json_error_t error;
This is not initialized or used with jansson ...
> + json_t *ret = NULL;
> + size_t i;
> +
> + switch (object->type) {
> + case VIR_JSON_TYPE_OBJECT:
> + ret = json_object();
> + if (!ret) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("failed to create JSON object: %s"),
> + error.text);
... so here you'll try to print an uninitialized pointer.
> + goto error;
> + }
[...]
All of the truncated ones have the same problem.
> + }
> + if (!ret) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("error creating JSON value: %s"),
> + error.text);
> + }
> + return ret;
> +
> + error:
> + json_decref(ret);
> + return NULL;
> +}
> +
> +
> +char *
> +virJSONValueToString(virJSONValuePtr object,
> + bool pretty)
> +{
> + size_t flags = JSON_ENCODE_ANY;
> + json_t *json;
> + json_error_t error;
> + char *str = NULL;
> +
> + if (pretty)
> + flags |= JSON_INDENT(2);
> + else
> + flags |= JSON_COMPACT;
> +
> + json = virJSONValueToJansson(object);
> + if (!json)
> + return NULL;
> +
> + str = json_dumps(json, flags);
> + if (!str) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("failed to format JSON %d:%d: %s"),
> + error.line, error.column, error.text);
Same problem.
> + }
> + json_decref(json);
> + return str;
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2025 Red Hat, Inc.