printer json BUGFIX opaque leaf-list attribute print
diff --git a/src/printer_json.c b/src/printer_json.c
index 312e30d..66ae154 100644
--- a/src/printer_json.c
+++ b/src/printer_json.c
@@ -4,7 +4,7 @@
  * @author Michal Vasko <mvasko@cesnet.cz>
  * @brief JSON printer for libyang data structure
  *
- * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
+ * Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
  *
  * This source code is licensed under BSD 3-Clause License (the "License").
  * You may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@
 
     uint16_t level_printed;     /* level where some data were already printed */
     struct ly_set open;         /* currently open array(s) */
-    const struct lyd_node *print_sibling_metadata;
+    const struct lyd_node *first_leaflist;  /**< first printed leaf-list instance, used when printing its metadata/attributes */
 };
 
 /**
@@ -410,19 +410,13 @@
  *
  * @param[in] ctx JSON printer context.
  * @param[in] node Opaq node where the attributes are placed.
- * @param[in] wdmod With-defaults module to mark that default attribute is supposed to be printed.
  * @return LY_ERR value.
  */
 static LY_ERR
-json_print_attribute(struct jsonpr_ctx *pctx, const struct lyd_node_opaq *node, const struct lys_module *wdmod)
+json_print_attribute(struct jsonpr_ctx *pctx, const struct lyd_node_opaq *node)
 {
     struct lyd_attr *attr;
 
-    if (wdmod) {
-        ly_print_(pctx->out, "%*s\"%s:default\":%strue", INDENT, wdmod->name, DO_FORMAT ? " " : "");
-        LEVEL_PRINTED;
-    }
-
     for (attr = node->attr; attr; attr = attr->next) {
         json_print_member2(pctx, &node->node, attr->format, &attr->name, 0);
 
@@ -511,7 +505,7 @@
         }
         ly_print_(pctx->out, "{%s", (DO_FORMAT ? "\n" : ""));
         LEVEL_INC;
-        LY_CHECK_RET(json_print_attribute(pctx, (struct lyd_node_opaq *)node, wdmod));
+        LY_CHECK_RET(json_print_attribute(pctx, (struct lyd_node_opaq *)node));
         LEVEL_DEC;
         ly_print_(pctx->out, "%s%*s}", DO_FORMAT ? "\n" : "", INDENT);
         LEVEL_PRINTED;
@@ -798,14 +792,14 @@
 
         LY_CHECK_RET(json_print_value(pctx, LYD_CTX(node), &((const struct lyd_node_term *)node)->value, node->schema->module));
 
-        if (!pctx->print_sibling_metadata) {
+        if (!pctx->first_leaflist) {
             if ((node->flags & LYD_DEFAULT) && (pctx->options & (LYD_PRINT_WD_ALL_TAG | LYD_PRINT_WD_IMPL_TAG))) {
                 /* we have implicit OR explicit default node, get with-defaults module */
                 wdmod = ly_ctx_get_module_implemented(LYD_CTX(node), "ietf-netconf-with-defaults");
             }
             if (node->meta || wdmod) {
                 /* we will be printing metadata for these siblings */
-                pctx->print_sibling_metadata = node;
+                pctx->first_leaflist = node;
             }
         }
     }
@@ -818,21 +812,20 @@
 }
 
 /**
- * @brief Print leaf-list's metadata in case they were marked in the last call to json_print_leaf_list().
+ * @brief Print leaf-list's metadata or opaque nodes attributes.
  * This function is supposed to be called when the leaf-list array is closed.
  *
  * @param[in] ctx JSON printer context.
  * @return LY_ERR value.
  */
 static LY_ERR
-json_print_metadata_leaflist(struct jsonpr_ctx *pctx)
+json_print_meta_attr_leaflist(struct jsonpr_ctx *pctx)
 {
     const struct lyd_node *prev, *node, *iter;
     const struct lys_module *wdmod = NULL;
+    const struct lyd_node_opaq *opaq = NULL;
 
-    if (!pctx->print_sibling_metadata) {
-        return LY_SUCCESS;
-    }
+    assert(pctx->first_leaflist);
 
     if (pctx->options & (LYD_PRINT_WD_ALL_TAG | LYD_PRINT_WD_IMPL_TAG)) {
         /* get with-defaults module */
@@ -840,19 +833,31 @@
     }
 
     /* node is the first instance of the leaf-list */
-    for (node = pctx->print_sibling_metadata, prev = pctx->print_sibling_metadata->prev;
+    for (node = pctx->first_leaflist, prev = pctx->first_leaflist->prev;
             prev->next && matching_node(node, prev);
             node = prev, prev = node->prev) {}
 
-    LY_CHECK_RET(json_print_member(pctx, node, 1));
+    if (node->schema) {
+        LY_CHECK_RET(json_print_member(pctx, node, 1));
+    } else {
+        opaq = (struct lyd_node_opaq *)node;
+        LY_CHECK_RET(json_print_member2(pctx, lyd_parent(node), opaq->format, &opaq->name, 1));
+    }
+
     ly_print_(pctx->out, "[%s", (DO_FORMAT ? "\n" : ""));
     LEVEL_INC;
     LY_LIST_FOR(node, iter) {
         PRINT_COMMA;
-        if (iter->meta || (iter->flags & LYD_DEFAULT)) {
+        if ((iter->schema && (iter->meta || (iter->flags & LYD_DEFAULT))) || (opaq && opaq->attr)) {
             ly_print_(pctx->out, "%*s%s", INDENT, DO_FORMAT ? "{\n" : "{");
             LEVEL_INC;
-            LY_CHECK_RET(json_print_metadata(pctx, iter, (iter->flags & LYD_DEFAULT) ? wdmod : NULL));
+
+            if (iter->schema) {
+                LY_CHECK_RET(json_print_metadata(pctx, iter, (iter->flags & LYD_DEFAULT) ? wdmod : NULL));
+            } else {
+                LY_CHECK_RET(json_print_attribute(pctx, (struct lyd_node_opaq *)iter));
+            }
+
             LEVEL_DEC;
             ly_print_(pctx->out, "%s%*s}", DO_FORMAT ? "\n" : "", INDENT);
         } else {
@@ -917,8 +922,13 @@
         }
         LEVEL_PRINTED;
 
-        /* attributes */
-        json_print_attributes(pctx, (const struct lyd_node *)node, 0);
+        if (!(node->hints & LYD_NODEHINT_LEAFLIST)) {
+            /* attributes */
+            json_print_attributes(pctx, (const struct lyd_node *)node, 0);
+        } else if (!pctx->first_leaflist && node->attr) {
+            /* attributes printed later */
+            pctx->first_leaflist = &node->node;
+        }
 
     }
     if (last && (node->hints & (LYD_NODEHINT_LIST | LYD_NODEHINT_LEAFLIST))) {
@@ -975,9 +985,9 @@
 
     pctx->level_printed = pctx->level;
 
-    if (pctx->print_sibling_metadata && !matching_node(node->next, pctx->print_sibling_metadata)) {
-        json_print_metadata_leaflist(pctx);
-        pctx->print_sibling_metadata = NULL;
+    if (pctx->first_leaflist && !matching_node(node->next, pctx->first_leaflist)) {
+        json_print_meta_attr_leaflist(pctx);
+        pctx->first_leaflist = NULL;
     }
 
     return LY_SUCCESS;