data tree FEATURE support for NETCONF messages
diff --git a/src/parser_json.c b/src/parser_json.c
index 8fd2f06..bccd286 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -40,8 +40,8 @@
  * Note that the structure maps to the lyd_ctx which is common for all the data parsers
  */
 struct lyd_json_ctx {
-    uint32_t parse_options;        /**< various @ref dataparseroptions. */
-    uint32_t validate_options;     /**< various @ref datavalidationoptions. */
+    uint32_t parse_opts;           /**< various @ref dataparseroptions. */
+    uint32_t val_opts;             /**< various @ref datavalidationoptions. */
     uint32_t int_opts;             /**< internal data parser options */
     uint32_t path_len;             /**< used bytes in the path buffer */
     char path[LYD_PARSER_BUFSIZE]; /**< buffer for the generated path */
@@ -214,12 +214,12 @@
         goto cleanup;
     }
     if (!mod) {
-        if (lydctx->parse_options & LYD_PARSE_STRICT) {
+        if (lydctx->parse_opts & LYD_PARSE_STRICT) {
             LOGVAL(lydctx->jsonctx->ctx, LYVE_REFERENCE, "No module named \"%.*s\" in the context.", prefix_len, prefix);
             ret = LY_EVALID;
             goto cleanup;
         }
-        if (!(lydctx->parse_options & LYD_PARSE_OPAQ)) {
+        if (!(lydctx->parse_opts & LYD_PARSE_OPAQ)) {
             ret = LY_ENOT;
             goto cleanup;
         }
@@ -229,12 +229,12 @@
     if (mod && (!parent || parent->schema)) {
         *snode_p = lys_find_child(parent ? parent->schema : NULL, mod, name, name_len, 0, getnext_opts);
         if (!*snode_p) {
-            if (lydctx->parse_options & LYD_PARSE_STRICT) {
+            if (lydctx->parse_opts & LYD_PARSE_STRICT) {
                 LOGVAL(lydctx->jsonctx->ctx, LYVE_REFERENCE, "Node \"%.*s\" not found in the \"%s\" module.",
                         name_len, name, mod->name);
                 ret = LY_EVALID;
                 goto cleanup;
-            } else if (!(lydctx->parse_options & LYD_PARSE_OPAQ)) {
+            } else if (!(lydctx->parse_opts & LYD_PARSE_OPAQ)) {
                 /* skip element with children */
                 ret = LY_ENOT;
                 goto cleanup;
@@ -435,7 +435,7 @@
         return LY_SUCCESS;
     }
 
-    if (lydctx->parse_options & LYD_PARSE_OPAQ) {
+    if (lydctx->parse_opts & LYD_PARSE_OPAQ) {
         /* backup parser */
         lyjson_ctx_backup(jsonctx);
         status = lyjson_ctx_status(jsonctx, 0);
@@ -585,7 +585,7 @@
                                 meta->name.name, strlen(meta->name.name), meta->value, ly_strlen(meta->value),
                                 &dynamic, LY_PREF_JSON, NULL, meta->hints);
                         LY_CHECK_GOTO(ret, cleanup);
-                    } else if (lydctx->parse_options & LYD_PARSE_STRICT) {
+                    } else if (lydctx->parse_opts & LYD_PARSE_STRICT) {
                         LOGVAL(lydctx->jsonctx->ctx, LYVE_REFERENCE,
                                 "Unknown (or not implemented) YANG module \"%s\" for metadata \"%s%s%s\".",
                                 meta->name.prefix, meta->name.prefix, ly_strlen(meta->name.prefix) ? ":" : "", meta->name.name);
@@ -594,7 +594,7 @@
                     }
                 }
                 /* add/correct flags */
-                lyd_parse_set_data_flags(node, &lydctx->node_when, &node->meta, lydctx->parse_options);
+                lyd_parse_set_data_flags(node, &lydctx->node_when, &node->meta, lydctx->parse_opts);
 
                 /* done */
                 break;
@@ -743,13 +743,13 @@
         /* get the element module */
         mod = ly_ctx_get_module_implemented2(ctx, prefix, prefix_len);
         if (!mod) {
-            if (lydctx->parse_options & LYD_PARSE_STRICT) {
+            if (lydctx->parse_opts & LYD_PARSE_STRICT) {
                 LOGVAL(ctx, LYVE_REFERENCE, "Prefix \"%.*s\" of the metadata \"%.*s\" does not match any module in the context.",
                         prefix_len, prefix, name_len, name);
                 ret = LY_EVALID;
                 goto cleanup;
             }
-            if (!(lydctx->parse_options & LYD_PARSE_OPAQ)) {
+            if (!(lydctx->parse_opts & LYD_PARSE_OPAQ)) {
                 /* skip element with children */
                 ret = lydjson_data_skip(lydctx->jsonctx);
                 LY_CHECK_GOTO(ret, cleanup);
@@ -772,7 +772,7 @@
             LY_CHECK_GOTO(ret, cleanup);
 
             /* add/correct flags */
-            lyd_parse_set_data_flags(node, &lydctx->node_when, &meta, lydctx->parse_options);
+            lyd_parse_set_data_flags(node, &lydctx->node_when, &meta, lydctx->parse_opts);
         } else {
             /* create attribute */
             const char *module_name;
@@ -845,7 +845,8 @@
     }
 }
 
-static LY_ERR lydjson_subtree_r(struct lyd_json_ctx *lydctx, struct lyd_node_inner *parent, struct lyd_node **first_p);
+static LY_ERR lydjson_subtree_r(struct lyd_json_ctx *lydctx, struct lyd_node *parent, struct lyd_node **first_p,
+        struct ly_set *parsed);
 
 /**
  * @brief Parse opaq node from the input.
@@ -900,7 +901,7 @@
     if ((*status_p == LYJSON_OBJECT) || (*status_p == LYJSON_OBJECT_EMPTY)) {
         /* process children */
         while (*status_p != LYJSON_OBJECT_CLOSED && *status_p != LYJSON_OBJECT_EMPTY) {
-            LY_CHECK_RET(lydjson_subtree_r(lydctx, (struct lyd_node_inner *)(*node_p), lyd_node_children_p(*node_p)));
+            LY_CHECK_RET(lydjson_subtree_r(lydctx, *node_p, lyd_node_child_p(*node_p), NULL));
             *status_p = lyjson_ctx_status(lydctx->jsonctx, 0);
         }
     } else if ((*status_p == LYJSON_ARRAY) || (*status_p == LYJSON_ARRAY_EMPTY)) {
@@ -911,7 +912,7 @@
         if ((*status_inner_p == LYJSON_OBJECT) || (*status_inner_p == LYJSON_OBJECT_EMPTY)) {
             /* but first process children of the object in the array */
             while (*status_inner_p != LYJSON_OBJECT_CLOSED && *status_inner_p != LYJSON_OBJECT_EMPTY) {
-                LY_CHECK_RET(lydjson_subtree_r(lydctx, (struct lyd_node_inner *)(*node_p), lyd_node_children_p(*node_p)));
+                LY_CHECK_RET(lydjson_subtree_r(lydctx, *node_p, lyd_node_child_p(*node_p), NULL));
                 *status_inner_p = lyjson_ctx_status(lydctx->jsonctx, 0);
             }
         }
@@ -922,12 +923,13 @@
         if (*status_inner_p != LYJSON_ARRAY_CLOSED) {
             assert(node_p);
             lydjson_maintain_children(parent, first_p, node_p);
-            return lydjson_parse_opaq(lydctx, name, name_len, prefix, prefix_len, parent, status_p, status_inner_p, first_p, node_p);
+            return lydjson_parse_opaq(lydctx, name, name_len, prefix, prefix_len, parent, status_p, status_inner_p,
+                    first_p, node_p);
         }
     }
 
     /* finish linking metadata */
-    LY_CHECK_RET(lydjson_metadata_finish(lydctx, lyd_node_children_p(*node_p)));
+    LY_CHECK_RET(lydjson_metadata_finish(lydctx, lyd_node_child_p(*node_p)));
 
     /* move after the item */
     return lyjson_ctx_next(lydctx->jsonctx, status_p);
@@ -953,9 +955,8 @@
  */
 static LY_ERR
 lydjson_parse_attribute(struct lyd_json_ctx *lydctx, struct lyd_node *attr_node, const struct lysc_node *snode,
-        const char *name, size_t name_len, const char *prefix, size_t prefix_len,
-        struct lyd_node_inner *parent, enum LYJSON_PARSER_STATUS *status_p, struct lyd_node **first_p,
-        struct lyd_node **node_p)
+        const char *name, size_t name_len, const char *prefix, size_t prefix_len, struct lyd_node *parent,
+        enum LYJSON_PARSER_STATUS *status_p, struct lyd_node **first_p, struct lyd_node **node_p)
 {
     LY_ERR ret = LY_SUCCESS;
     enum LYJSON_PARSER_STATUS status_inner;
@@ -988,15 +989,16 @@
         }
 
         /* backup parser options to parse unknown metadata as opaq nodes and try to resolve them later */
-        prev_opts = lydctx->parse_options;
-        lydctx->parse_options &= ~LYD_PARSE_STRICT;
-        lydctx->parse_options |= LYD_PARSE_OPAQ;
+        prev_opts = lydctx->parse_opts;
+        lydctx->parse_opts &= ~LYD_PARSE_STRICT;
+        lydctx->parse_opts |= LYD_PARSE_OPAQ;
 
         ret = lydjson_parse_opaq(lydctx, prefix ? prefix - 1 : name - 1, prefix ? prefix_len + name_len + 2 : name_len + 1,
-                NULL, 0, parent, status_p, status_inner == LYJSON_ERROR ? status_p : &status_inner, first_p, node_p);
+                NULL, 0, (struct lyd_node_inner *)parent, status_p, status_inner == LYJSON_ERROR ? status_p : &status_inner,
+                first_p, node_p);
 
         /* restore the parser options */
-        lydctx->parse_options = prev_opts;
+        lydctx->parse_opts = prev_opts;
     } else {
         ret = lydjson_metadata(lydctx, snode, attr_node);
     }
@@ -1056,13 +1058,13 @@
 
             /* process children */
             while (*status != LYJSON_OBJECT_CLOSED && *status != LYJSON_OBJECT_EMPTY) {
-                ret = lydjson_subtree_r(lydctx, (struct lyd_node_inner *)*node, lyd_node_children_p(*node));
+                ret = lydjson_subtree_r(lydctx, *node, lyd_node_child_p(*node), NULL);
                 LY_CHECK_ERR_RET(ret, LOG_LOCBACK(1, 1, 0, 0), ret);
                 *status = lyjson_ctx_status(lydctx->jsonctx, 0);
             }
 
             /* finish linking metadata */
-            ret = lydjson_metadata_finish(lydctx, lyd_node_children_p(*node));
+            ret = lydjson_metadata_finish(lydctx, lyd_node_child_p(*node));
             LY_CHECK_ERR_RET(ret, LOG_LOCBACK(1, 1, 0, 0), ret);
 
             if (snode->nodetype == LYS_LIST) {
@@ -1071,14 +1073,14 @@
                 LY_CHECK_ERR_RET(ret, LOG_LOCBACK(1, 1, 0, 0), ret);
             }
 
-            if (!(lydctx->parse_options & LYD_PARSE_ONLY)) {
+            if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
                 /* new node validation, autodelete CANNOT occur, all nodes are new */
-                ret = lyd_validate_new(lyd_node_children_p(*node), snode, NULL, NULL);
+                ret = lyd_validate_new(lyd_node_child_p(*node), snode, NULL, NULL);
                 LY_CHECK_ERR_RET(ret, LOG_LOCBACK(1, 1, 0, 0), ret);
 
                 /* add any missing default children */
-                ret = lyd_new_implicit_r(*node, lyd_node_children_p(*node), NULL, NULL, &lydctx->node_types,
-                        &lydctx->node_when, (lydctx->validate_options & LYD_VALIDATE_NO_STATE) ?
+                ret = lyd_new_implicit_r(*node, lyd_node_child_p(*node), NULL, NULL, &lydctx->node_types,
+                        &lydctx->node_when, (lydctx->val_opts & LYD_VALIDATE_NO_STATE) ?
                         LYD_IMPLICIT_NO_STATE : 0, NULL);
                 LY_CHECK_ERR_RET(ret, LOG_LOCBACK(1, 1, 0, 0), ret);
             }
@@ -1094,19 +1096,19 @@
 
             /* parse any data tree with correct options */
             /* first backup the current options and then make the parser to process data as opaq nodes */
-            prev_opts = lydctx->parse_options;
-            lydctx->parse_options &= ~LYD_PARSE_STRICT;
-            lydctx->parse_options |= LYD_PARSE_OPAQ;
+            prev_opts = lydctx->parse_opts;
+            lydctx->parse_opts &= ~LYD_PARSE_STRICT;
+            lydctx->parse_opts |= LYD_PARSE_OPAQ;
 
             /* process the anydata content */
             while (*status != LYJSON_OBJECT_CLOSED && *status != LYJSON_OBJECT_EMPTY) {
-                ret = lydjson_subtree_r(lydctx, NULL, &tree);
+                ret = lydjson_subtree_r(lydctx, NULL, &tree, NULL);
                 LY_CHECK_RET(ret);
                 *status = lyjson_ctx_status(lydctx->jsonctx, 0);
             }
 
             /* restore parser options */
-            lydctx->parse_options = prev_opts;
+            lydctx->parse_opts = prev_opts;
 
             /* finish linking metadata */
             ret = lydjson_metadata_finish(lydctx, &tree);
@@ -1137,10 +1139,11 @@
  * @param[in] lydctx JSON data parser context.
  * @param[in] parent Data parent of the subtree, must be set if @p first is not.
  * @param[in,out] first_p Pointer to the variable holding the first top-level sibling, must be set if @p parent is not.
+ * @param[in,out] parsed Optional set to add all the parsed siblings into.
  * @return LY_ERR value.
  */
 static LY_ERR
-lydjson_subtree_r(struct lyd_json_ctx *lydctx, struct lyd_node_inner *parent, struct lyd_node **first_p)
+lydjson_subtree_r(struct lyd_json_ctx *lydctx, struct lyd_node *parent, struct lyd_node **first_p, struct ly_set *parsed)
 {
     LY_ERR ret = LY_SUCCESS;
     enum LYJSON_PARSER_STATUS status = lyjson_ctx_status(lydctx->jsonctx, 0);
@@ -1161,7 +1164,7 @@
 
     if (!is_meta || name_len || prefix_len) {
         /* get the schema node */
-        ret = lydjson_get_snode(lydctx, is_meta, prefix, prefix_len, name, name_len, parent, &snode);
+        ret = lydjson_get_snode(lydctx, is_meta, prefix, prefix_len, name, name_len, (struct lyd_node_inner *)parent, &snode);
         if (ret == LY_ENOT) {
             /* skip element with children */
             ret = lydjson_data_skip(lydctx->jsonctx);
@@ -1188,7 +1191,7 @@
                 ret = LY_EVALID;
                 goto cleanup;
             }
-            attr_node = &parent->node;
+            attr_node = parent;
             snode = attr_node->schema;
         }
         ret = lydjson_parse_attribute(lydctx, attr_node, snode, name, name_len, prefix, prefix_len, parent, &status,
@@ -1196,7 +1199,7 @@
         LY_CHECK_GOTO(ret, cleanup);
     } else if (!snode) {
         /* parse as an opaq node */
-        assert((lydctx->parse_options & LYD_PARSE_OPAQ) || (lydctx->int_opts));
+        assert((lydctx->parse_opts & LYD_PARSE_OPAQ) || (lydctx->int_opts));
 
         /* move to the second item in the name/X pair */
         ret = lyjson_ctx_next(lydctx->jsonctx, &status);
@@ -1211,8 +1214,8 @@
             status_inner = LYJSON_ERROR;
         }
 
-        ret = lydjson_parse_opaq(lydctx, name, name_len, prefix, prefix_len,
-                parent, &status, status_inner == LYJSON_ERROR ? &status : &status_inner, first_p, &node);
+        ret = lydjson_parse_opaq(lydctx, name, name_len, prefix, prefix_len, (struct lyd_node_inner *)parent, &status,
+                status_inner == LYJSON_ERROR ? &status : &status_inner, first_p, &node);
         LY_CHECK_GOTO(ret, cleanup);
     } else {
         /* parse as a standard lyd_node but it can still turn out to be an opaque node */
@@ -1239,10 +1242,10 @@
 
             /* process all the values/objects */
             do {
-                lydjson_maintain_children(parent, first_p, &node);
+                lydjson_maintain_children((struct lyd_node_inner *)parent, first_p, &node);
 
-                ret = lydjson_parse_instance(lydctx, parent, first_p, snode, name, name_len, prefix, prefix_len,
-                        &status, &node);
+                ret = lydjson_parse_instance(lydctx, (struct lyd_node_inner *)parent, first_p, snode, name, name_len,
+                        prefix, prefix_len, &status, &node);
                 if (ret == LY_EINVAL) {
                     goto representation_error;
                 } else if (ret) {
@@ -1273,7 +1276,8 @@
             }
 
             /* process the value/object */
-            ret = lydjson_parse_instance(lydctx, parent, first_p, snode, name, name_len, prefix, prefix_len, &status, &node);
+            ret = lydjson_parse_instance(lydctx, (struct lyd_node_inner *)parent, first_p, snode, name, name_len,
+                    prefix, prefix_len, &status, &node);
             if (ret == LY_EINVAL) {
                 goto representation_error;
             } else if (ret) {
@@ -1290,13 +1294,18 @@
     }
 
     /* finally connect the parsed node */
-    lydjson_maintain_children(parent, first_p, &node);
+    lydjson_maintain_children((struct lyd_node_inner *)parent, first_p, &node);
+
+    /* rememeber a successfully parsed node */
+    if (parsed) {
+        ly_set_add(parsed, node, 1, NULL);
+    }
 
     /* success */
     goto cleanup;
 
 representation_error:
-    LOG_LOCSET(NULL, &parent->node, NULL, NULL);
+    LOG_LOCSET(NULL, parent, NULL, NULL);
     LOGVAL(ctx, LYVE_SYNTAX_JSON, "The %s \"%s\" is expected to be represented as JSON %s, but input data contains name/%s.",
             lys_nodetype2str(snode->nodetype), snode->name, expected, lyjson_token2str(status));
     LOG_LOCBACK(0, parent ? 1 : 0, 0, 0);
@@ -1312,14 +1321,14 @@
  *
  * @param[in] ctx libyang context
  * @param[in] in Input structure.
- * @param[in] parse_options Options for parser, see @ref dataparseroptions.
- * @param[in] validate_options Options for the validation phase, see @ref datavalidationoptions.
+ * @param[in] parse_opts Options for parser, see @ref dataparseroptions.
+ * @param[in] val_opts Options for the validation phase, see @ref datavalidationoptions.
  * @param[out] lydctx_p Data parser context to finish validation.
  * @param[out] status Storage for the current context's status
  * @return LY_ERR value.
  */
 static LY_ERR
-lyd_parse_json_init(const struct ly_ctx *ctx, struct ly_in *in, uint32_t parse_options, uint32_t validate_options,
+lyd_parse_json_init(const struct ly_ctx *ctx, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts,
         struct lyd_json_ctx **lydctx_p, enum LYJSON_PARSER_STATUS *status)
 {
     LY_ERR ret = LY_SUCCESS;
@@ -1332,8 +1341,8 @@
     /* init context */
     lydctx = calloc(1, sizeof *lydctx);
     LY_CHECK_ERR_RET(!lydctx, LOGMEM(ctx), LY_EMEM);
-    lydctx->parse_options = parse_options;
-    lydctx->validate_options = validate_options;
+    lydctx->parse_opts = parse_opts;
+    lydctx->val_opts = val_opts;
     lydctx->free = lyd_json_ctx_free;
 
     /* starting top-level */
@@ -1360,394 +1369,79 @@
 }
 
 LY_ERR
-lyd_parse_json_data(const struct ly_ctx *ctx, struct ly_in *in, uint32_t parse_options, uint32_t validate_options,
-        struct lyd_node **tree_p, struct lyd_ctx **lydctx_p)
+lyd_parse_json(const struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_node **first_p, struct ly_in *in,
+        uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type, struct ly_set *parsed, struct lyd_ctx **lydctx_p)
 {
-    LY_ERR ret = LY_SUCCESS;
+    LY_ERR rc = LY_SUCCESS;
     struct lyd_json_ctx *lydctx = NULL;
     enum LYJSON_PARSER_STATUS status;
+    uint32_t int_opts;
 
-    assert(tree_p);
-    *tree_p = NULL;
-
-    ret = lyd_parse_json_init(ctx, in, parse_options, validate_options, &lydctx, &status);
-    LY_CHECK_GOTO(ret || status == LYJSON_END || status == LYJSON_OBJECT_EMPTY, cleanup);
+    rc = lyd_parse_json_init(ctx, in, parse_opts, val_opts, &lydctx, &status);
+    LY_CHECK_GOTO(rc || status == LYJSON_END || status == LYJSON_OBJECT_EMPTY, cleanup);
 
     assert(status == LYJSON_OBJECT);
 
+    switch (data_type) {
+    case LYD_TYPE_YANG_DATA:
+        int_opts = LYD_INTOPT_WITH_SIBLINGS;
+        break;
+    case LYD_TYPE_YANG_RPC:
+        int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
+        break;
+    case LYD_TYPE_YANG_NOTIF:
+        int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
+        break;
+    case LYD_TYPE_YANG_REPLY:
+        int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
+        break;
+    default:
+        LOGINT(ctx);
+        rc = LY_EINT;
+        goto cleanup;
+    }
+    lydctx->int_opts = int_opts;
+
+    /* find the operation node if it exists already */
+    LY_CHECK_GOTO(rc = lyd_parser_find_operation(parent, int_opts, &lydctx->op_node), cleanup);
+
     /* read subtree(s) */
-    while (lydctx->jsonctx->in->current[0] && status != LYJSON_OBJECT_CLOSED) {
-        ret = lydjson_subtree_r(lydctx, NULL, tree_p);
-        LY_CHECK_GOTO(ret, cleanup);
+    while (lydctx->jsonctx->in->current[0] && (status != LYJSON_OBJECT_CLOSED)) {
+        rc = lydjson_subtree_r(lydctx, parent, first_p, parsed);
+        LY_CHECK_GOTO(rc, cleanup);
 
         status = lyjson_ctx_status(lydctx->jsonctx, 0);
+
+        if (!(int_opts & LYD_INTOPT_WITH_SIBLINGS)) {
+            break;
+        }
+    }
+
+    if ((int_opts & LYD_INTOPT_NO_SIBLINGS) && lydctx->jsonctx->in->current[0] &&
+            (lyjson_ctx_status(lydctx->jsonctx, 0) != LYJSON_OBJECT_CLOSED)) {
+        LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling node.");
+        rc = LY_EVALID;
+        goto cleanup;
+    }
+    if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY)) && !lydctx->op_node) {
+        LOGVAL(ctx, LYVE_DATA, "Missing the operation node.");
+        rc = LY_EVALID;
+        goto cleanup;
     }
 
     /* finish linking metadata */
-    ret = lydjson_metadata_finish(lydctx, tree_p);
-    LY_CHECK_GOTO(ret, cleanup);
+    rc = lydjson_metadata_finish(lydctx, parent ? lyd_node_child_p(parent) : first_p);
+    LY_CHECK_GOTO(rc, cleanup);
 
 cleanup:
     /* there should be no unresolved types stored */
-    assert(!(parse_options & LYD_PARSE_ONLY) || (!lydctx->node_types.count && !lydctx->meta_types.count &&
+    assert(!(parse_opts & LYD_PARSE_ONLY) || (!lydctx->node_types.count && !lydctx->meta_types.count &&
             !lydctx->node_when.count));
 
-    if (ret) {
+    if (rc) {
         lyd_json_ctx_free((struct lyd_ctx *)lydctx);
-        lyd_free_all(*tree_p);
-        *tree_p = NULL;
     } else {
         *lydctx_p = (struct lyd_ctx *)lydctx;
     }
-
-    return ret;
-}
-
-#if 0
-/**
- * @brief Parse optional JSON envelope around the Notification data, including the eventTime data.
- *
- * @param[in] jsonctx JSON parser context
- * @param[out] envp_p Pointer to the created envelope opaq container.
- * @param[out] status Storage for the current context's status
- * @return LY_SUCCESS if the envelope present and successfully parsed.
- * @return LY_ENOT in case there is not the expected envelope.
- * @return LY_ERR in case of parsing failure.
- */
-static LY_ERR
-lydjson_notif_envelope(struct lyjson_ctx *jsonctx, struct lyd_node **envp_p, enum LYJSON_PARSER_STATUS *status_p)
-{
-    LY_ERR ret = LY_ENOT, r;
-    const char *name, *prefix, *value = NULL;
-    size_t name_len, prefix_len, value_len;
-    ly_bool is_attr, dynamic = 0;
-    enum LYJSON_PARSER_STATUS status;
-    struct lyd_node *et;
-
-    *envp_p = NULL;
-
-    /* backup the context */
-    lyjson_ctx_backup(jsonctx);
-
-    /* "notification" envelope */
-    lydjson_parse_name(jsonctx->value, jsonctx->value_len, &name, &name_len, &prefix, &prefix_len, &is_attr);
-    LY_CHECK_GOTO(is_attr, cleanup);
-    LY_CHECK_GOTO(prefix_len != 13 || strncmp(prefix, "ietf-restconf", 13), cleanup);
-    LY_CHECK_GOTO(name_len != 12 || strncmp(name, "notification", name_len), cleanup);
-
-    r = lyjson_ctx_next(jsonctx, &status);
-    LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
-    LY_CHECK_GOTO(status != LYJSON_OBJECT, cleanup);
-
-    /* "eventTime" child */
-    lydjson_parse_name(jsonctx->value, jsonctx->value_len, &name, &name_len, &prefix, &prefix_len, &is_attr);
-    LY_CHECK_GOTO(prefix_len || is_attr, cleanup);
-    LY_CHECK_GOTO(name_len != 9 || strncmp(name, "eventTime", name_len), cleanup);
-
-    /* go for the data */
-    r = lyjson_ctx_next(jsonctx, &status);
-    LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
-    LY_CHECK_GOTO(status != LYJSON_STRING, cleanup);
-
-    value = jsonctx->value;
-    value_len = jsonctx->value_len;
-    dynamic = jsonctx->dynamic;
-    jsonctx->dynamic = 0;
-
-    r = lyjson_ctx_next(jsonctx, &status);
-    LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
-    LY_CHECK_GOTO(status != LYJSON_OBJECT, cleanup);
-    /* now the notificationContent is expected, which will be parsed by the caller */
-
-    /* create notification envelope */
-    ret = lyd_create_opaq(jsonctx->ctx, "notification", ly_strlen_const("notification"), NULL, 0,
-            "ietf-restconf", ly_strlen_const("ietf-restconf"), "", ly_strlen_const(""), NULL, LY_PREF_JSON, NULL,
-            LYD_NODEHINT_ENVELOPE, envp_p);
-    LY_CHECK_GOTO(ret, cleanup);
-    /* create notification envelope */
-    ret = lyd_create_opaq(jsonctx->ctx, "eventTime", ly_strlen_const("eventTime"), NULL, 0,
-            "ietf-restconf", ly_strlen_const("ietf-restconf"), value, value_len, &dynamic, LY_PREF_JSON, NULL,
-            LYD_VALHINT_STRING, &et);
-    LY_CHECK_GOTO(ret, cleanup);
-    /* insert eventTime into notification */
-    lyd_insert_node(*envp_p, NULL, et);
-
-    ret = LY_SUCCESS;
-    *status_p = status;
-cleanup:
-    if (ret) {
-        /* restore the context */
-        lyjson_ctx_restore(jsonctx);
-        if (dynamic) {
-            free((char *)value);
-        }
-    }
-    return ret;
-}
-
-#endif
-
-LY_ERR
-lyd_parse_json_notif(const struct ly_ctx *ctx, struct ly_in *in, struct lyd_node **tree_p, struct lyd_node **ntf_p)
-{
-    LY_ERR ret = LY_SUCCESS;
-    struct lyd_json_ctx *lydctx = NULL;
-    struct lyd_node *tree = NULL;
-    enum LYJSON_PARSER_STATUS status;
-
-    /* init */
-    ret = lyd_parse_json_init(ctx, in, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &lydctx, &status);
-    LY_CHECK_GOTO(ret || status == LYJSON_END || status == LYJSON_OBJECT_EMPTY, cleanup);
-
-    lydctx->int_opts = LYD_INTOPT_NOTIF;
-
-#if 0
-    /* parse "notification" and "eventTime", if present */
-    ret = lydjson_notif_envelope(lydctx->jsonctx, &ntf_e, &status);
-    if (ret == LY_ENOT) {
-        ret = LY_SUCCESS;
-    } else if (ret) {
-        goto cleanup;
-    }
-#endif
-
-    assert(status == LYJSON_OBJECT);
-
-    /* read subtree */
-    ret = lydjson_subtree_r(lydctx, NULL, &tree);
-    LY_CHECK_GOTO(ret, cleanup);
-
-    /* finish linking metadata */
-    ret = lydjson_metadata_finish(lydctx, &tree);
-    LY_CHECK_GOTO(ret, cleanup);
-
-    /* make sure we have parsed some notification */
-    if (!lydctx->op_node) {
-        LOGVAL(ctx, LYVE_DATA, "Missing the \"notification\" node.");
-        ret = LY_EVALID;
-        goto cleanup;
-    } else if (lydctx->jsonctx->in->current[0] && (lyjson_ctx_status(lydctx->jsonctx, 0) != LYJSON_OBJECT_CLOSED)) {
-        LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling element of \"%s\".",
-                tree->schema->name);
-        ret = LY_EVALID;
-        goto cleanup;
-    }
-
-    if (ntf_p) {
-        *ntf_p = lydctx->op_node;
-    }
-    assert(tree);
-    if (tree_p) {
-        *tree_p = tree;
-    }
-
-cleanup:
-    /* we have used parse_only flag */
-    assert(!lydctx || (!lydctx->node_types.count && !lydctx->meta_types.count && !lydctx->node_when.count));
-
-    lyd_json_ctx_free((struct lyd_ctx *)lydctx);
-    if (ret) {
-        lyd_free_all(tree);
-    }
-    return ret;
-}
-
-#if 0
-/**
- * @brief Parse optional JSON envelope around the processed content.
- *
- * @param[in] jsonctx JSON parser context
- * @param[in] parent Parent node (some other envelope).
- * @param[in] module_key Name of the module where the envelope element is expected.
- * @param[in] object_id Name of the envelope object.
- * @param[out] envp_p Pointer to the created envelope opaq container.
- * @param[out] status Storage for the current context's status
- * @return LY_SUCCESS if the envelope present and successfully parsed.
- * @return LY_ENOT in case there is not the expected envelope.
- * @return LY_ERR in case of parsing failure.
- */
-static LY_ERR
-lydjson_object_envelope(struct lyjson_ctx *jsonctx, struct lyd_node *parent, const char *module_key,
-        const char *object_id, struct lyd_node **envp_p, enum LYJSON_PARSER_STATUS *status)
-{
-    LY_ERR ret = LY_ENOT, r;
-    const char *name, *prefix;
-    size_t name_len, prefix_len;
-    ly_bool is_attr;
-
-    *envp_p = NULL;
-
-    /* "id" envelope */
-    lydjson_parse_name(jsonctx->value, jsonctx->value_len, &name, &name_len, &prefix, &prefix_len, &is_attr);
-    LY_CHECK_GOTO(is_attr, cleanup);
-    LY_CHECK_GOTO(lydjson_get_node_prefix(parent, prefix, prefix_len, &prefix, &prefix_len), cleanup);
-    LY_CHECK_GOTO(prefix_len != strlen(module_key) || strncmp(prefix, module_key, prefix_len), cleanup);
-    LY_CHECK_GOTO(name_len != strlen(object_id) || strncmp(name, object_id, name_len), cleanup);
-
-    r = lyjson_ctx_next(jsonctx, status);
-    LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
-    LY_CHECK_GOTO(*status != LYJSON_OBJECT, cleanup);
-
-    /* create the object envelope */
-    ret = lyd_create_opaq(jsonctx->ctx, object_id, strlen(object_id), NULL, 0, module_key, ly_strlen(module_key), "", 0,
-            NULL, LY_PREF_JSON, NULL, LYD_NODEHINT_ENVELOPE, envp_p);
-    LY_CHECK_GOTO(ret, cleanup);
-
-    if (parent) {
-        lyd_insert_node(parent, NULL, *envp_p);
-    }
-
-    ret = LY_SUCCESS;
-cleanup:
-    return ret;
-}
-
-static LY_ERR
-lydjson_object_envelope_close(struct lyjson_ctx *jsonctx, const char *object_id, enum LYJSON_PARSER_STATUS *status)
-{
-    LY_CHECK_RET(lyjson_ctx_next(jsonctx, status));
-    if (*status == LYJSON_END) {
-        LOGVAL(jsonctx->ctx, LY_VCODE_EOF);
-        return LY_EVALID;
-    } else if (*status != LYJSON_OBJECT_CLOSED) {
-        LOGVAL(jsonctx->ctx, LYVE_SYNTAX, "Unexpected sibling member \"%.*s\" of \"%s\".",
-                jsonctx->value_len, jsonctx->value, object_id);
-        return LY_EVALID;
-    }
-    return LY_SUCCESS;
-}
-
-#endif
-
-LY_ERR
-lyd_parse_json_rpc(const struct ly_ctx *ctx, struct ly_in *in, struct lyd_node **tree_p, struct lyd_node **op_p)
-{
-    LY_ERR ret = LY_SUCCESS;
-    struct lyd_json_ctx *lydctx = NULL;
-    struct lyd_node *tree = NULL;
-    enum LYJSON_PARSER_STATUS status;
-
-    /* init */
-    ret = lyd_parse_json_init(ctx, in, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &lydctx, &status);
-    LY_CHECK_GOTO(ret || status == LYJSON_END || status == LYJSON_OBJECT_EMPTY, cleanup);
-
-    lydctx->int_opts = LYD_INTOPT_RPC;
-
-#if 0
-    /* process envelope(s), if present */
-
-    /* process rpc */
-    ret = lydjson_object_envelope(lydctx->jsonctx, NULL, "ietf-netconf", "rpc", &rpc_e, &status);
-    if (ret == LY_ENOT) {
-        ret = LY_SUCCESS;
-        goto parse_content;
-    } else if (ret) {
-        goto cleanup;
-    }
-    /* process action */
-    ret = lydjson_object_envelope(lydctx->jsonctx, rpc_e, "yang", "action", &act_e, &status);
-    if (ret == LY_ENOT) {
-        ret = LY_SUCCESS;
-        goto parse_content;
-    } else if (ret) {
-        goto cleanup;
-    }
-
-parse_content:
-#endif
-    assert(status == LYJSON_OBJECT);
-
-    /* read subtree(s) */
-    ret = lydjson_subtree_r(lydctx, NULL, &tree);
-    LY_CHECK_GOTO(ret, cleanup);
-
-    /* finish linking metadata */
-    ret = lydjson_metadata_finish(lydctx, &tree);
-    LY_CHECK_GOTO(ret, cleanup);
-
-    /* make sure we have parsed some operation */
-    if (!lydctx->op_node) {
-        LOGVAL(ctx, LYVE_DATA, "Missing the rpc/action node.");
-        ret = LY_EVALID;
-        goto cleanup;
-    } else if (lydctx->jsonctx->in->current[0] && (lyjson_ctx_status(lydctx->jsonctx, 0) != LYJSON_OBJECT_CLOSED)) {
-        LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling element of \"%s\".",
-                tree->schema->name);
-        ret = LY_EVALID;
-        goto cleanup;
-    }
-
-    if (op_p) {
-        *op_p = lydctx->op_node;
-    }
-    assert(tree);
-    if (tree_p) {
-        *tree_p = tree;
-    }
-
-cleanup:
-    /* we have used parse_only flag */
-    assert(!lydctx || (!lydctx->node_types.count && !lydctx->meta_types.count && !lydctx->node_when.count));
-
-    lyd_json_ctx_free((struct lyd_ctx *)lydctx);
-    if (ret) {
-        lyd_free_all(tree);
-    }
-    return ret;
-}
-
-LY_ERR
-lyd_parse_json_reply(const struct ly_ctx *ctx, struct ly_in *in, struct lyd_node **tree_p, struct lyd_node **op_p)
-{
-    LY_ERR ret = LY_SUCCESS;
-    struct lyd_json_ctx *lydctx = NULL;
-    struct lyd_node *tree = NULL;
-    enum LYJSON_PARSER_STATUS status;
-
-    /* init */
-    ret = lyd_parse_json_init(ctx, in, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &lydctx, &status);
-    LY_CHECK_GOTO(ret || status == LYJSON_END || status == LYJSON_OBJECT_EMPTY, cleanup);
-
-    lydctx->int_opts = LYD_INTOPT_REPLY;
-
-#if 0
-    /* parse "rpc-reply", if any */
-    ret = lydjson_object_envelope(lydctx->jsonctx, NULL, "ietf-netconf", "rpc-reply", &rpcr_e, &status);
-    if (ret == LY_ENOT) {
-        ret = LY_SUCCESS;
-    } else if (ret) {
-        goto cleanup;
-    }
-#endif
-
-    assert(status == LYJSON_OBJECT);
-
-    /* read subtree(s) */
-    while (lydctx->jsonctx->in->current[0] && status != LYJSON_OBJECT_CLOSED) {
-        ret = lydjson_subtree_r(lydctx, NULL, &tree);
-        LY_CHECK_GOTO(ret, cleanup);
-
-        status = lyjson_ctx_status(lydctx->jsonctx, 0);
-    }
-
-    /* finish linking metadata */
-    ret = lydjson_metadata_finish(lydctx, &tree);
-    LY_CHECK_GOTO(ret, cleanup);
-
-    if (op_p) {
-        *op_p = lydctx->op_node;
-    }
-    if (tree_p) {
-        *tree_p = tree;
-    }
-
-cleanup:
-    /* we have used parse_only flag */
-    assert(!lydctx || (!lydctx->node_types.count && !lydctx->meta_types.count && !lydctx->node_when.count));
-
-    lyd_json_ctx_free((struct lyd_ctx *)lydctx);
-    if (ret) {
-        lyd_free_all(tree);
-    }
-    return ret;
+    return rc;
 }