parser json UPDATE support for opaque nodes with invalid-encoded value

Fixes #2033
diff --git a/src/parser_json.c b/src/parser_json.c
index 9cbd5d8..40eb568 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -338,6 +338,55 @@
 }
 
 /**
+ * @brief Get the hint for the data type parsers according to the current JSON parser context.
+ *
+ * @param[in] jsonctx JSON parser context. The context is supposed to be on a value.
+ * @param[in,out] status Pointer to the current context status,
+ * in some circumstances the function manipulates with the context so the status is updated.
+ * @param[out] type_hint_p Pointer to the variable to store the result.
+ * @return LY_SUCCESS in case of success.
+ * @return LY_EINVAL in case of invalid context status not referring to a value.
+ */
+static LY_ERR
+lydjson_value_type_hint(struct lyjson_ctx *jsonctx, enum LYJSON_PARSER_STATUS *status_p, uint32_t *type_hint_p)
+{
+    *type_hint_p = 0;
+
+    if (*status_p == LYJSON_ARRAY) {
+        /* only [null] */
+        LY_CHECK_RET(lyjson_ctx_next(jsonctx, status_p));
+        if (*status_p != LYJSON_NULL) {
+            LOGVAL(jsonctx->ctx, LYVE_SYNTAX_JSON,
+                    "Expected JSON name/value or special name/[null], but input data contains name/[%s].",
+                    lyjson_token2str(*status_p));
+            return LY_EINVAL;
+        }
+
+        LY_CHECK_RET(lyjson_ctx_next(jsonctx, NULL));
+        if (lyjson_ctx_status(jsonctx) != LYJSON_ARRAY_CLOSED) {
+            LOGVAL(jsonctx->ctx, LYVE_SYNTAX_JSON, "Expected array end, but input data contains %s.",
+                    lyjson_token2str(*status_p));
+            return LY_EINVAL;
+        }
+
+        *type_hint_p = LYD_VALHINT_EMPTY;
+    } else if (*status_p == LYJSON_STRING) {
+        *type_hint_p = LYD_VALHINT_STRING | LYD_VALHINT_NUM64;
+    } else if (*status_p == LYJSON_NUMBER) {
+        *type_hint_p = LYD_VALHINT_DECNUM;
+    } else if ((*status_p == LYJSON_FALSE) || (*status_p == LYJSON_TRUE)) {
+        *type_hint_p = LYD_VALHINT_BOOLEAN;
+    } else if (*status_p == LYJSON_NULL) {
+        *type_hint_p = 0;
+    } else {
+        LOGVAL(jsonctx->ctx, LYVE_SYNTAX_JSON, "Unexpected input data %s.", lyjson_token2str(*status_p));
+        return LY_EINVAL;
+    }
+
+    return LY_SUCCESS;
+}
+
+/**
  * @brief Check that the input data are parseable as the @p list.
  *
  * Checks for all the list's keys. Function does not revert the context state.
@@ -354,7 +403,7 @@
     enum LYJSON_PARSER_STATUS status = lyjson_ctx_status(jsonctx);
     struct ly_set key_set = {0};
     const struct lysc_node *snode;
-    uint32_t i;
+    uint32_t i, hints;
 
     assert(list && (list->nodetype == LYS_LIST));
 
@@ -402,7 +451,9 @@
                         goto cleanup;
                     }
 
-                    rc = lys_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, LY_VALUE_JSON, NULL);
+                    rc = lydjson_value_type_hint(jsonctx, &status, &hints);
+                    LY_CHECK_GOTO(rc, cleanup);
+                    rc = ly_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, LY_VALUE_JSON, NULL, hints);
                     LY_CHECK_GOTO(rc, cleanup);
 
                     /* key with a valid value, remove from the set */
@@ -430,55 +481,6 @@
 }
 
 /**
- * @brief Get the hint for the data type parsers according to the current JSON parser context.
- *
- * @param[in] lydctx JSON data parser context. The context is supposed to be on a value.
- * @param[in,out] status Pointer to the current context status,
- * in some circumstances the function manipulates with the context so the status is updated.
- * @param[out] type_hint_p Pointer to the variable to store the result.
- * @return LY_SUCCESS in case of success.
- * @return LY_EINVAL in case of invalid context status not referring to a value.
- */
-static LY_ERR
-lydjson_value_type_hint(struct lyd_json_ctx *lydctx, enum LYJSON_PARSER_STATUS *status_p, uint32_t *type_hint_p)
-{
-    *type_hint_p = 0;
-
-    if (*status_p == LYJSON_ARRAY) {
-        /* only [null] */
-        LY_CHECK_RET(lyjson_ctx_next(lydctx->jsonctx, status_p));
-        if (*status_p != LYJSON_NULL) {
-            LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX_JSON,
-                    "Expected JSON name/value or special name/[null], but input data contains name/[%s].",
-                    lyjson_token2str(*status_p));
-            return LY_EINVAL;
-        }
-
-        LY_CHECK_RET(lyjson_ctx_next(lydctx->jsonctx, NULL));
-        if (lyjson_ctx_status(lydctx->jsonctx) != LYJSON_ARRAY_CLOSED) {
-            LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX_JSON, "Expected array end, but input data contains %s.",
-                    lyjson_token2str(*status_p));
-            return LY_EINVAL;
-        }
-
-        *type_hint_p = LYD_VALHINT_EMPTY;
-    } else if (*status_p == LYJSON_STRING) {
-        *type_hint_p = LYD_VALHINT_STRING | LYD_VALHINT_NUM64;
-    } else if (*status_p == LYJSON_NUMBER) {
-        *type_hint_p = LYD_VALHINT_DECNUM;
-    } else if ((*status_p == LYJSON_FALSE) || (*status_p == LYJSON_TRUE)) {
-        *type_hint_p = LYD_VALHINT_BOOLEAN;
-    } else if (*status_p == LYJSON_NULL) {
-        *type_hint_p = 0;
-    } else {
-        LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX_JSON, "Unexpected input data %s.", lyjson_token2str(*status_p));
-        return LY_EINVAL;
-    }
-
-    return LY_SUCCESS;
-}
-
-/**
  * @brief Check in advance if the input data are parsable according to the provided @p snode.
  *
  * Note that the checks are done only in case the LYD_PARSE_OPAQ is allowed. Otherwise the same checking
@@ -518,12 +520,10 @@
         case LYS_LEAFLIST:
         case LYS_LEAF:
             /* value may not be valid in which case we parse it as an opaque node */
-            ret = lydjson_value_type_hint(lydctx, &status, type_hint_p);
-            if (ret) {
+            if ((ret = lydjson_value_type_hint(jsonctx, &status, type_hint_p))) {
                 break;
             }
-
-            if (lys_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, LY_VALUE_JSON, NULL)) {
+            if (ly_value_validate(NULL, snode, jsonctx->value, jsonctx->value_len, LY_VALUE_JSON, NULL, *type_hint_p)) {
                 ret = LY_ENOT;
             }
             break;
@@ -536,7 +536,7 @@
             break;
         }
     } else if (snode->nodetype & LYD_NODE_TERM) {
-        ret = lydjson_value_type_hint(lydctx, &status, type_hint_p);
+        ret = lydjson_value_type_hint(jsonctx, &status, type_hint_p);
     }
 
     /* restore parser */
@@ -846,7 +846,7 @@
         LY_CHECK_GOTO(rc = lyjson_ctx_next(lydctx->jsonctx, &status), cleanup);
 
         /* get value hints */
-        LY_CHECK_GOTO(rc = lydjson_value_type_hint(lydctx, &status, &val_hints), cleanup);
+        LY_CHECK_GOTO(rc = lydjson_value_type_hint(lydctx->jsonctx, &status, &val_hints), cleanup);
 
         if (node->schema) {
             /* create metadata */
@@ -969,7 +969,7 @@
         dynamic = lydctx->jsonctx->dynamic;
         lydctx->jsonctx->dynamic = 0;
 
-        LY_CHECK_RET(lydjson_value_type_hint(lydctx, status_inner_p, &type_hint));
+        LY_CHECK_RET(lydjson_value_type_hint(lydctx->jsonctx, status_inner_p, &type_hint));
     }
 
     /* get the module name */