diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 51044b0af8..1566d11e41 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1632,13 +1632,16 @@ virJSONValueObjectCreate;
 virJSONValueObjectCreateVArgs;
 virJSONValueObjectForeachKeyValue;
 virJSONValueObjectGet;
+virJSONValueObjectGetArray;
 virJSONValueObjectGetBoolean;
+virJSONValueObjectGetByType;
 virJSONValueObjectGetKey;
 virJSONValueObjectGetNumberDouble;
 virJSONValueObjectGetNumberInt;
 virJSONValueObjectGetNumberLong;
 virJSONValueObjectGetNumberUint;
 virJSONValueObjectGetNumberUlong;
+virJSONValueObjectGetObject;
 virJSONValueObjectGetString;
 virJSONValueObjectGetValue;
 virJSONValueObjectHasKey;
diff --git a/src/util/virjson.c b/src/util/virjson.c
index 7d4ece6465..29e2c39636 100644
--- a/src/util/virjson.c
+++ b/src/util/virjson.c
@@ -766,6 +766,21 @@ virJSONValueObjectGet(virJSONValuePtr object,
 }
 
 
+/* Return the value associated with KEY within OBJECT, but return NULL
+ * if the key is missing or if value is not the correct TYPE.  */
+virJSONValuePtr
+virJSONValueObjectGetByType(virJSONValuePtr object,
+                            const char *key,
+                            virJSONType type)
+{
+    virJSONValuePtr value = virJSONValueObjectGet(object, key);
+
+    if (value && value->type == type)
+        return value;
+    return NULL;
+}
+
+
 int
 virJSONValueObjectKeysNumber(virJSONValuePtr object)
 {
@@ -1057,13 +1072,10 @@ virJSONValueNewArrayFromBitmap(virBitmapPtr bitmap)
 }
 
 
-int
+bool
 virJSONValueIsNull(virJSONValuePtr val)
 {
-    if (val->type != VIR_JSON_TYPE_NULL)
-        return 0;
-
-    return 1;
+    return val->type == VIR_JSON_TYPE_NULL;
 }
 
 
@@ -1071,11 +1083,8 @@ const char *
 virJSONValueObjectGetString(virJSONValuePtr object,
                             const char *key)
 {
-    virJSONValuePtr val;
-    if (object->type != VIR_JSON_TYPE_OBJECT)
-        return NULL;
+    virJSONValuePtr val = virJSONValueObjectGet(object, key);
 
-    val = virJSONValueObjectGet(object, key);
     if (!val)
         return NULL;
 
@@ -1088,11 +1097,8 @@ virJSONValueObjectGetNumberInt(virJSONValuePtr object,
                                const char *key,
                                int *value)
 {
-    virJSONValuePtr val;
-    if (object->type != VIR_JSON_TYPE_OBJECT)
-        return -1;
+    virJSONValuePtr val = virJSONValueObjectGet(object, key);
 
-    val = virJSONValueObjectGet(object, key);
     if (!val)
         return -1;
 
@@ -1105,11 +1111,8 @@ virJSONValueObjectGetNumberUint(virJSONValuePtr object,
                                 const char *key,
                                 unsigned int *value)
 {
-    virJSONValuePtr val;
-    if (object->type != VIR_JSON_TYPE_OBJECT)
-        return -1;
+    virJSONValuePtr val = virJSONValueObjectGet(object, key);
 
-    val = virJSONValueObjectGet(object, key);
     if (!val)
         return -1;
 
@@ -1122,11 +1125,8 @@ virJSONValueObjectGetNumberLong(virJSONValuePtr object,
                                 const char *key,
                                 long long *value)
 {
-    virJSONValuePtr val;
-    if (object->type != VIR_JSON_TYPE_OBJECT)
-        return -1;
+    virJSONValuePtr val = virJSONValueObjectGet(object, key);
 
-    val = virJSONValueObjectGet(object, key);
     if (!val)
         return -1;
 
@@ -1139,11 +1139,8 @@ virJSONValueObjectGetNumberUlong(virJSONValuePtr object,
                                  const char *key,
                                  unsigned long long *value)
 {
-    virJSONValuePtr val;
-    if (object->type != VIR_JSON_TYPE_OBJECT)
-        return -1;
+    virJSONValuePtr val = virJSONValueObjectGet(object, key);
 
-    val = virJSONValueObjectGet(object, key);
     if (!val)
         return -1;
 
@@ -1156,11 +1153,8 @@ virJSONValueObjectGetNumberDouble(virJSONValuePtr object,
                                   const char *key,
                                   double *value)
 {
-    virJSONValuePtr val;
-    if (object->type != VIR_JSON_TYPE_OBJECT)
-        return -1;
+    virJSONValuePtr val = virJSONValueObjectGet(object, key);
 
-    val = virJSONValueObjectGet(object, key);
     if (!val)
         return -1;
 
@@ -1173,11 +1167,8 @@ virJSONValueObjectGetBoolean(virJSONValuePtr object,
                              const char *key,
                              bool *value)
 {
-    virJSONValuePtr val;
-    if (object->type != VIR_JSON_TYPE_OBJECT)
-        return -1;
+    virJSONValuePtr val = virJSONValueObjectGet(object, key);
 
-    val = virJSONValueObjectGet(object, key);
     if (!val)
         return -1;
 
@@ -1185,15 +1176,26 @@ virJSONValueObjectGetBoolean(virJSONValuePtr object,
 }
 
 
+virJSONValuePtr
+virJSONValueObjectGetObject(virJSONValuePtr object, const char *key)
+{
+    return virJSONValueObjectGetByType(object, key, VIR_JSON_TYPE_OBJECT);
+}
+
+
+virJSONValuePtr
+virJSONValueObjectGetArray(virJSONValuePtr object, const char *key)
+{
+    return virJSONValueObjectGetByType(object, key, VIR_JSON_TYPE_ARRAY);
+}
+
+
 int
 virJSONValueObjectIsNull(virJSONValuePtr object,
                          const char *key)
 {
-    virJSONValuePtr val;
-    if (object->type != VIR_JSON_TYPE_OBJECT)
-        return -1;
+    virJSONValuePtr val = virJSONValueObjectGet(object, key);
 
-    val = virJSONValueObjectGet(object, key);
     if (!val)
         return -1;
 
diff --git a/src/util/virjson.h b/src/util/virjson.h
index e871b2ea9f..a7df6e591b 100644
--- a/src/util/virjson.h
+++ b/src/util/virjson.h
@@ -110,6 +110,8 @@ int virJSONValueArrayAppend(virJSONValuePtr object, virJSONValuePtr value);
 
 int virJSONValueObjectHasKey(virJSONValuePtr object, const char *key);
 virJSONValuePtr virJSONValueObjectGet(virJSONValuePtr object, const char *key);
+virJSONValuePtr virJSONValueObjectGetByType(virJSONValuePtr object,
+                                            const char *key, virJSONType type);
 
 bool virJSONValueIsArray(virJSONValuePtr array);
 int virJSONValueArraySize(const virJSONValue *array);
@@ -129,7 +131,11 @@ int virJSONValueGetNumberDouble(virJSONValuePtr object, double *value);
 int virJSONValueGetBoolean(virJSONValuePtr object, bool *value);
 int virJSONValueGetArrayAsBitmap(const virJSONValue *val, virBitmapPtr *bitmap)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
-int virJSONValueIsNull(virJSONValuePtr object);
+bool virJSONValueIsNull(virJSONValuePtr object);
+virJSONValuePtr virJSONValueObjectGetObject(virJSONValuePtr object,
+                                            const char *key);
+virJSONValuePtr virJSONValueObjectGetArray(virJSONValuePtr object,
+                                           const char *key);
 
 const char *virJSONValueObjectGetString(virJSONValuePtr object, const char *key);
 int virJSONValueObjectGetNumberInt(virJSONValuePtr object, const char *key, int *value);
diff --git a/tests/jsontest.c b/tests/jsontest.c
index f226c9251e..34a07ee264 100644
--- a/tests/jsontest.c
+++ b/tests/jsontest.c
@@ -118,6 +118,114 @@ testJSONAddRemove(const void *data)
 }
 
 
+static int
+testJSONLookup(const void *data)
+{
+    const struct testInfo *info = data;
+    virJSONValuePtr json;
+    virJSONValuePtr value = NULL;
+    char *result = NULL;
+    int rc;
+    int number;
+    const char *str;
+    int ret = -1;
+
+    json = virJSONValueFromString(info->doc);
+    if (!json) {
+        VIR_TEST_VERBOSE("Fail to parse %s\n", info->doc);
+        ret = -1;
+        goto cleanup;
+    }
+
+    value = virJSONValueObjectGetObject(json, "a");
+    if (value) {
+        if (!info->pass) {
+            VIR_TEST_VERBOSE("lookup for 'a' in '%s' should have failed\n",
+                             info->doc);
+            goto cleanup;
+        } else {
+            result = virJSONValueToString(value, false);
+            if (STRNEQ_NULLABLE(result, "{}")) {
+                VIR_TEST_VERBOSE("lookup for 'a' in '%s' found '%s' but "
+                                 "should have found '{}'\n",
+                                 info->doc, NULLSTR(result));
+                goto cleanup;
+            }
+            VIR_FREE(result);
+        }
+    } else if (info->pass) {
+        VIR_TEST_VERBOSE("lookup for 'a' in '%s' should have succeeded\n",
+                         info->doc);
+        goto cleanup;
+    }
+
+    number = 2;
+    rc = virJSONValueObjectGetNumberInt(json, "b", &number);
+    if (rc == 0) {
+        if (!info->pass) {
+            VIR_TEST_VERBOSE("lookup for 'b' in '%s' should have failed\n",
+                             info->doc);
+            goto cleanup;
+        } else if (number != 1) {
+            VIR_TEST_VERBOSE("lookup for 'b' in '%s' found %d but "
+                             "should have found 1\n",
+                             info->doc, number);
+            goto cleanup;
+        }
+    } else if (info->pass) {
+        VIR_TEST_VERBOSE("lookup for 'b' in '%s' should have succeeded\n",
+                         info->doc);
+        goto cleanup;
+    }
+
+    str = virJSONValueObjectGetString(json, "c");
+    if (str) {
+        if (!info->pass) {
+            VIR_TEST_VERBOSE("lookup for 'c' in '%s' should have failed\n",
+                             info->doc);
+            goto cleanup;
+        } else if (STRNEQ(str, "str")) {
+            VIR_TEST_VERBOSE("lookup for 'c' in '%s' found '%s' but "
+                             "should have found 'str'\n", info->doc, str);
+                goto cleanup;
+        }
+    } else if (info->pass) {
+        VIR_TEST_VERBOSE("lookup for 'c' in '%s' should have succeeded\n",
+                         info->doc);
+        goto cleanup;
+    }
+
+    value = virJSONValueObjectGetArray(json, "d");
+    if (value) {
+        if (!info->pass) {
+            VIR_TEST_VERBOSE("lookup for 'd' in '%s' should have failed\n",
+                             info->doc);
+            goto cleanup;
+        } else {
+            result = virJSONValueToString(value, false);
+            if (STRNEQ_NULLABLE(result, "[]")) {
+                VIR_TEST_VERBOSE("lookup for 'd' in '%s' found '%s' but "
+                                 "should have found '[]'\n",
+                                 info->doc, NULLSTR(result));
+                goto cleanup;
+            }
+            VIR_FREE(result);
+        }
+    } else if (info->pass) {
+        VIR_TEST_VERBOSE("lookup for 'd' in '%s' should have succeeded\n",
+                         info->doc);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    virJSONValueFree(json);
+    VIR_FREE(result);
+    return ret;
+}
+
+
 static int
 testJSONCopy(const void *data)
 {
@@ -319,6 +427,21 @@ mymain(void)
                        "[ {[\"key1\", \"key2\"]: \"value\"} ]");
     DO_TEST_PARSE_FAIL("object with unterminated key", "{ \"key:7 }");
 
+    DO_TEST_FULL("lookup on array", Lookup,
+                 "[ 1 ]", NULL, false);
+    DO_TEST_FULL("lookup on string", Lookup,
+                 "\"str\"", NULL, false);
+    DO_TEST_FULL("lookup on integer", Lookup,
+                 "1", NULL, false);
+    DO_TEST_FULL("lookup with missing key", Lookup,
+                 "{ }", NULL, false);
+    DO_TEST_FULL("lookup with wrong type", Lookup,
+                 "{ \"a\": 1, \"b\": \"str\", \"c\": [], \"d\": {} }",
+                 NULL, false);
+    DO_TEST_FULL("lookup with correct type", Lookup,
+                 "{ \"a\": {}, \"b\": 1, \"c\": \"str\", \"d\": [] }",
+                 NULL, true);
+
     return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }