parser json BUGFIX skipping objects

Fixes sysrepo/sysrepo#3006
diff --git a/src/parser_json.c b/src/parser_json.c
index 71d6efc..764d771 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -183,7 +183,10 @@
 }
 
 /**
- * @brief Skip the current JSON item (baed on status).
+ * @brief Skip the current JSON item (based on status).
+ *
+ * The JSON context is moved to the last "status" of the JSON item so to completely
+ * finish the skip, one more JSON context move is required.
  *
  * @param[in] jsonctx JSON context with the input data to skip.
  * @return LY_ERR value.
@@ -206,7 +209,6 @@
 
     if ((status == LYJSON_OBJECT) && (current != LYJSON_OBJECT) && (current != LYJSON_ARRAY)) {
         /* no nested objects */
-        LY_CHECK_RET(lyjson_ctx_next(jsonctx, NULL));
         return LY_SUCCESS;
     }
 
@@ -283,14 +285,6 @@
             ret = LY_EVALID;
             goto cleanup;
         }
-        if (!(lydctx->parse_opts & LYD_PARSE_OPAQ)) {
-            /* skip element with children */
-            ret = lydjson_data_skip(lydctx->jsonctx);
-            LY_CHECK_GOTO(ret, cleanup);
-
-            ret = LY_ENOT;
-            goto cleanup;
-        }
     }
 
     /* get the schema node */
@@ -329,13 +323,6 @@
                 }
                 ret = LY_EVALID;
                 goto cleanup;
-            } else if (!(lydctx->parse_opts & LYD_PARSE_OPAQ)) {
-                /* skip element with children */
-                ret = lydjson_data_skip(lydctx->jsonctx);
-                LY_CHECK_GOTO(ret, cleanup);
-
-                ret = LY_ENOT;
-                goto cleanup;
             }
         } else {
             /* check that schema node is valid and can be used */
@@ -1580,19 +1567,24 @@
                 first_p, &node);
         LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
     } else if (!snode) {
-        /* parse as an opaq node */
-        assert((lydctx->parse_opts & LYD_PARSE_OPAQ) || (lydctx->int_opts));
+        if (!(lydctx->parse_opts & LYD_PARSE_OPAQ)) {
+            /* skip element with children */
+            r = lydjson_data_skip(lydctx->jsonctx);
+            LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
+        } else {
+            /* parse as an opaq node */
 
-        /* opaq node cannot have an empty string as the name. */
-        if (name_len == 0) {
-            LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX_JSON, "A JSON object member name cannot be a zero-length string.");
-            r = LY_EVALID;
-            LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);
+            /* opaq node cannot have an empty string as the name. */
+            if (name_len == 0) {
+                LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX_JSON, "A JSON object member name cannot be a zero-length string.");
+                r = LY_EVALID;
+                LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);
+            }
+
+            /* move to the second item in the name/X pair and parse opaq */
+            r = lydjson_ctx_next_parse_opaq(lydctx, name, name_len, prefix, prefix_len, parent, &status, first_p, &node);
+            LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
         }
-
-        /* move to the second item in the name/X pair and parse opaq */
-        r = lydjson_ctx_next_parse_opaq(lydctx, name, name_len, prefix, prefix_len, parent, &status, first_p, &node);
-        LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
     } else {
         /* parse as a standard lyd_node but it can still turn out to be an opaque node */
 
diff --git a/tests/utests/data/test_parser_json.c b/tests/utests/data/test_parser_json.c
index 09466bb..285152e 100644
--- a/tests/utests/data/test_parser_json.c
+++ b/tests/utests/data/test_parser_json.c
@@ -428,12 +428,10 @@
     assert_non_null(leaf = (struct lyd_node_term *)leaf->next);
     CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "d", 1, LYS_LEAF, 1, 0, NULL, 0);
     CHECK_LOG_CTX(NULL, NULL);
-
     CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS,
             "{\"a:l1\":[{\"a\":\"a\",\"b\":\"b\",\"c\":1,\"d\":\"d\"}]}");
     lyd_free_all(tree);
 
-    /*  */
     CHECK_PARSE_LYD("{\"a:l1\":[{\"c\":1,\"b\":\"b\",\"a\":\"a\"}]}", LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, tree);
     CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "l1",
             1, LYS_LIST, 0, 0, NULL, 0);
@@ -448,11 +446,16 @@
     CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "c",
             1, LYS_LEAF, 1, 0, NULL, 0);
     CHECK_LOG_CTX(NULL, NULL);
-
     CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS,
             "{\"a:l1\":[{\"a\":\"a\",\"b\":\"b\",\"c\":1}]}");
     lyd_free_all(tree);
 
+    /* skip unknown nested nodes */
+    data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":3,\"counters\":{\"count1\":\"c1\",\"count2\":\"c2\"}}]}";
+    CHECK_PARSE_LYD(data, LYD_PARSE_ONLY, 0, tree);
+    CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":3}]}");
+    lyd_free_all(tree);
+
     data = "{\"a:cp\":{\"@\":{\"a:hint\":1}}}";
     CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
     assert_non_null(tree);
@@ -461,7 +464,6 @@
             1, LYS_CONTAINER, 0, 0, NULL, 0);
     CHECK_LYD_META(tree->meta, 1, "hint", 0, 1,  INT8, "1", 1);
     assert_null(tree->meta->next);
-
     CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
     lyd_free_all(tree);
 }