blob: 7627110bc9e2fa5fd0f10fc77f8a0b84d27ba611 [file] [log] [blame]
Radek Krejci94ca54b2015-07-08 15:48:47 +02001/**
2 * @file printer/json.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief JSON printer for libyang data structure
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejci94ca54b2015-07-08 15:48:47 +020013 */
14
15#include <stdlib.h>
16#include <stdio.h>
17#include <string.h>
18#include <assert.h>
Radek Krejci7511f402015-07-10 09:56:30 +020019#include <inttypes.h>
Radek Krejci94ca54b2015-07-08 15:48:47 +020020
Radek Krejci998a0b82015-08-17 13:14:36 +020021#include "common.h"
Radek Krejci76b07902015-10-09 09:11:25 +020022#include "printer.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020023#include "tree_data.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020024#include "resolve.h"
25#include "tree_internal.h"
Radek Krejci94ca54b2015-07-08 15:48:47 +020026
27#define INDENT ""
28#define LEVEL (level*2)
29
Radek Krejci46180b52016-08-31 16:01:32 +020030static void json_print_nodes(struct lyout *out, int level, const struct lyd_node *root, int withsiblings, int toplevel,
31 int options);
Radek Krejci94ca54b2015-07-08 15:48:47 +020032
Radek Krejci382e7f92016-01-12 17:15:47 +010033static int
34json_print_string(struct lyout *out, const char *text)
35{
36 unsigned int i, n;
37
38 if (!text) {
39 return 0;
40 }
41
42 ly_write(out, "\"", 1);
43 for (i = n = 0; text[i]; i++) {
zyinter200856c0f132016-11-17 10:59:23 +080044 if (text[i] >= 0 && text[i] < 0x20) {
Radek Krejci382e7f92016-01-12 17:15:47 +010045 /* control character */
46 n += ly_print(out, "\\u%.4X");
47 } else {
48 switch (text[i]) {
49 case '"':
50 n += ly_print(out, "\\\"");
51 break;
52 case '\\':
53 n += ly_print(out, "\\\\");
54 break;
55 default:
56 ly_write(out, &text[i], 1);
57 n++;
58 }
59 }
60 }
61 ly_write(out, "\"", 1);
62
63 return n + 2;
64}
65
Radek Krejci94ca54b2015-07-08 15:48:47 +020066static void
Radek Krejci1eefeb32016-04-15 16:01:46 +020067json_print_attrs(struct lyout *out, int level, const struct lyd_node *node, const struct lys_module *wdmod)
Radek Krejcida61fb22015-10-30 11:10:03 +010068{
69 struct lyd_attr *attr;
70
Radek Krejci1eefeb32016-04-15 16:01:46 +020071 if (wdmod) {
72 ly_print(out, "%*s\"%s:default\":\"true\"", LEVEL, INDENT, wdmod->name);
73 ly_print(out, "%s%s", node->attr ? "," : "", (level ? "\n" : ""));
74 }
Radek Krejcida61fb22015-10-30 11:10:03 +010075 for (attr = node->attr; attr; attr = attr->next) {
76 if (attr->module != node->schema->module) {
Radek Krejci382e7f92016-01-12 17:15:47 +010077 ly_print(out, "%*s\"%s:%s\":", LEVEL, INDENT, attr->module->name, attr->name);
Radek Krejcida61fb22015-10-30 11:10:03 +010078 } else {
Radek Krejci382e7f92016-01-12 17:15:47 +010079 ly_print(out, "%*s\"%s\":", LEVEL, INDENT, attr->name);
Radek Krejcida61fb22015-10-30 11:10:03 +010080 }
Radek Krejci382e7f92016-01-12 17:15:47 +010081 json_print_string(out, attr->value ? attr->value : "");
Michal Vasko95068c42016-03-24 14:58:11 +010082 ly_print(out, "%s%s", attr->next ? "," : "", (level ? "\n" : ""));
Radek Krejcida61fb22015-10-30 11:10:03 +010083 }
84}
85
86static void
Radek Krejci46180b52016-08-31 16:01:32 +020087json_print_leaf(struct lyout *out, int level, const struct lyd_node *node, int onlyvalue, int toplevel, int options)
Radek Krejci94ca54b2015-07-08 15:48:47 +020088{
Michal Vasko4c183312015-09-25 10:41:47 +020089 struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *)node;
Radek Krejcida61fb22015-10-30 11:10:03 +010090 const char *schema = NULL;
Radek Krejci1eefeb32016-04-15 16:01:46 +020091 const struct lys_module *wdmod = NULL;
Radek Krejci9b6aad22016-09-20 15:55:51 +020092 LY_DATA_TYPE datatype;
Radek Krejci9ad23f42016-10-31 15:46:52 +010093 const struct lys_type *type;
Radek Krejci1eefeb32016-04-15 16:01:46 +020094
Radek Krejci46180b52016-08-31 16:01:32 +020095 if ((node->dflt && (options & (LYP_WD_ALL_TAG | LYP_WD_IMPL_TAG))) ||
96 (!node->dflt && (options & LYP_WD_ALL_TAG) && lyd_wd_default(leaf))) {
97 /* we have implicit OR explicit default node */
Radek Krejci1eefeb32016-04-15 16:01:46 +020098 /* get with-defaults module */
99 wdmod = ly_ctx_get_module(node->schema->module->ctx, "ietf-netconf-with-defaults", NULL);
100 }
Radek Krejci94ca54b2015-07-08 15:48:47 +0200101
Radek Krejci5a988152015-07-15 11:16:26 +0200102 if (!onlyvalue) {
Michal Vasko635bd452016-05-18 13:26:55 +0200103 if (toplevel || !node->parent || nscmp(node, node->parent)) {
Radek Krejci5a988152015-07-15 11:16:26 +0200104 /* print "namespace" */
Michal Vasko6c629ac2016-02-15 14:08:23 +0100105 schema = lys_node_module(node->schema)->name;
Michal Vasko95068c42016-03-24 14:58:11 +0100106 ly_print(out, "%*s\"%s:%s\":%s", LEVEL, INDENT, schema, node->schema->name, (level ? " " : ""));
Radek Krejci94ca54b2015-07-08 15:48:47 +0200107 } else {
Michal Vasko95068c42016-03-24 14:58:11 +0100108 ly_print(out, "%*s\"%s\":%s", LEVEL, INDENT, node->schema->name, (level ? " " : ""));
Radek Krejci94ca54b2015-07-08 15:48:47 +0200109 }
Radek Krejci94ca54b2015-07-08 15:48:47 +0200110 }
Radek Krejcie4748472015-07-08 18:00:22 +0200111
Radek Krejci9b6aad22016-09-20 15:55:51 +0200112 datatype = leaf->value_type & LY_DATA_TYPE_MASK;
113contentprint:
114 switch (datatype) {
Radek Krejcie4748472015-07-08 18:00:22 +0200115 case LY_TYPE_BINARY:
116 case LY_TYPE_STRING:
Radek Krejci3e3affe2015-07-09 15:38:40 +0200117 case LY_TYPE_BITS:
Radek Krejci5b315a92015-07-10 13:18:45 +0200118 case LY_TYPE_ENUM:
Radek Krejciac8aac62015-07-10 15:36:35 +0200119 case LY_TYPE_IDENT:
Radek Krejcic5090c32015-08-12 09:46:19 +0200120 case LY_TYPE_INST:
Radek Krejcic27114c2016-09-20 10:02:28 +0200121 case LY_TYPE_INT64:
122 case LY_TYPE_UINT64:
严军喜100794891758ff62016-10-25 10:14:47 +0800123 case LY_TYPE_DEC64:
Michal Vasko44913842016-04-13 14:20:41 +0200124 json_print_string(out, leaf->value_str);
Radek Krejciac8aac62015-07-10 15:36:35 +0200125 break;
Radek Krejcib1c12512015-08-11 11:22:04 +0200126
Radek Krejcib1c12512015-08-11 11:22:04 +0200127 case LY_TYPE_INT8:
128 case LY_TYPE_INT16:
129 case LY_TYPE_INT32:
Radek Krejcib1c12512015-08-11 11:22:04 +0200130 case LY_TYPE_UINT8:
131 case LY_TYPE_UINT16:
132 case LY_TYPE_UINT32:
严军喜100794891758ff62016-10-25 10:14:47 +0800133 case LY_TYPE_BOOL:
Michal Vasko44913842016-04-13 14:20:41 +0200134 ly_print(out, "%s", leaf->value_str[0] ? leaf->value_str : "null");
Radek Krejcib1c12512015-08-11 11:22:04 +0200135 break;
136
Radek Krejci9b6aad22016-09-20 15:55:51 +0200137 case LY_TYPE_LEAFREF:
Radek Krejci1899d6a2016-11-03 13:48:07 +0100138 type = lyd_leaf_type(leaf, 1);
Radek Krejci9ad23f42016-10-31 15:46:52 +0100139 if (!type) {
140 /* error */
141 ly_print(out, "\"(!error!)\"");
142 break;
143 }
144 datatype = type->base;
Radek Krejci9b6aad22016-09-20 15:55:51 +0200145 goto contentprint;
146
Radek Krejcib1c12512015-08-11 11:22:04 +0200147 case LY_TYPE_EMPTY:
Radek Krejci76b07902015-10-09 09:11:25 +0200148 ly_print(out, "[null]");
Michal Vasko58110162015-07-15 15:50:16 +0200149 break;
Radek Krejcib1c12512015-08-11 11:22:04 +0200150
Radek Krejcie4748472015-07-08 18:00:22 +0200151 default:
Michal Vasko493bea72015-07-16 16:08:12 +0200152 /* error */
Radek Krejci76b07902015-10-09 09:11:25 +0200153 ly_print(out, "\"(!error!)\"");
Radek Krejcie4748472015-07-08 18:00:22 +0200154 }
155
Radek Krejci382e7f92016-01-12 17:15:47 +0100156 /* print attributes as sibling leafs */
Radek Krejci1eefeb32016-04-15 16:01:46 +0200157 if (!onlyvalue && (node->attr || wdmod)) {
Radek Krejcida61fb22015-10-30 11:10:03 +0100158 if (schema) {
Michal Vasko95068c42016-03-24 14:58:11 +0100159 ly_print(out, ",%s%*s\"@%s:%s\":%s{%s", (level ? "\n" : ""), LEVEL, INDENT, schema, node->schema->name,
160 (level ? " " : ""), (level ? "\n" : ""));
Radek Krejcida61fb22015-10-30 11:10:03 +0100161 } else {
Michal Vasko95068c42016-03-24 14:58:11 +0100162 ly_print(out, ",%s%*s\"@%s\":%s{%s", (level ? "\n" : ""), LEVEL, INDENT, node->schema->name,
163 (level ? " " : ""), (level ? "\n" : ""));
Radek Krejcida61fb22015-10-30 11:10:03 +0100164 }
Radek Krejci1eefeb32016-04-15 16:01:46 +0200165 json_print_attrs(out, level + 1, node, wdmod);
Radek Krejcida61fb22015-10-30 11:10:03 +0100166 ly_print(out, "%*s}", LEVEL, INDENT);
167 }
168
Radek Krejcib1c12512015-08-11 11:22:04 +0200169 return;
Radek Krejci94ca54b2015-07-08 15:48:47 +0200170}
171
Michal Vaskoab8e4402015-07-17 12:54:28 +0200172static void
Radek Krejci46180b52016-08-31 16:01:32 +0200173json_print_container(struct lyout *out, int level, const struct lyd_node *node, int toplevel, int options)
Michal Vasko98763c62015-07-17 13:47:00 +0200174{
175 const char *schema;
Michal Vasko98763c62015-07-17 13:47:00 +0200176
Michal Vasko635bd452016-05-18 13:26:55 +0200177 if (toplevel || !node->parent || nscmp(node, node->parent)) {
Michal Vasko98763c62015-07-17 13:47:00 +0200178 /* print "namespace" */
Michal Vasko6c629ac2016-02-15 14:08:23 +0100179 schema = lys_node_module(node->schema)->name;
Michal Vasko95068c42016-03-24 14:58:11 +0100180 ly_print(out, "%*s\"%s:%s\":%s{%s", LEVEL, INDENT, schema, node->schema->name, (level ? " " : ""), (level ? "\n" : ""));
Michal Vasko98763c62015-07-17 13:47:00 +0200181 } else {
Michal Vasko95068c42016-03-24 14:58:11 +0100182 ly_print(out, "%*s\"%s\":%s{%s", LEVEL, INDENT, node->schema->name, (level ? " " : ""), (level ? "\n" : ""));
Michal Vasko98763c62015-07-17 13:47:00 +0200183 }
Michal Vasko95068c42016-03-24 14:58:11 +0100184 if (level) {
185 level++;
186 }
Radek Krejcida61fb22015-10-30 11:10:03 +0100187 if (node->attr) {
Michal Vasko95068c42016-03-24 14:58:11 +0100188 ly_print(out, "%*s\"@\":%s{%s", LEVEL, INDENT, (level ? " " : ""), (level ? "\n" : ""));
Radek Krejci1eefeb32016-04-15 16:01:46 +0200189 json_print_attrs(out, (level? level + 1 : level), node, NULL);
Michal Vasko95068c42016-03-24 14:58:11 +0100190 ly_print(out, "%*s}", LEVEL, INDENT);
191 if (node->child) {
192 ly_print(out, ",%s", (level ? "\n" : ""));
193 }
Radek Krejcida61fb22015-10-30 11:10:03 +0100194 }
Radek Krejci46180b52016-08-31 16:01:32 +0200195 json_print_nodes(out, level, node->child, 1, 0, options);
Michal Vasko95068c42016-03-24 14:58:11 +0100196 if (level) {
197 level--;
198 }
Radek Krejci76b07902015-10-09 09:11:25 +0200199 ly_print(out, "%*s}", LEVEL, INDENT);
Michal Vasko98763c62015-07-17 13:47:00 +0200200}
201
202static void
Radek Krejci46180b52016-08-31 16:01:32 +0200203json_print_leaf_list(struct lyout *out, int level, const struct lyd_node *node, int is_list, int toplevel, int options)
Michal Vasko98763c62015-07-17 13:47:00 +0200204{
Radek Krejcida61fb22015-10-30 11:10:03 +0100205 const char *schema = NULL;
Michal Vasko1e62a092015-12-01 12:27:20 +0100206 const struct lyd_node *list = node;
Radek Krejcida61fb22015-10-30 11:10:03 +0100207 int flag_empty = 0, flag_attrs = 0;
Radek Krejci23238922015-10-27 17:13:34 +0100208
Radek Krejcie8775162016-09-14 13:08:58 +0200209 if (is_list && !list->child) {
Radek Krejci23238922015-10-27 17:13:34 +0100210 /* empty, e.g. in case of filter */
211 flag_empty = 1;
212 }
Michal Vasko98763c62015-07-17 13:47:00 +0200213
Michal Vasko635bd452016-05-18 13:26:55 +0200214 if (toplevel || !node->parent || nscmp(node, node->parent)) {
Michal Vasko98763c62015-07-17 13:47:00 +0200215 /* print "namespace" */
Michal Vasko6c629ac2016-02-15 14:08:23 +0100216 schema = lys_node_module(node->schema)->name;
Radek Krejci23238922015-10-27 17:13:34 +0100217 ly_print(out, "%*s\"%s:%s\":", LEVEL, INDENT, schema, node->schema->name);
Michal Vasko98763c62015-07-17 13:47:00 +0200218 } else {
Radek Krejci23238922015-10-27 17:13:34 +0100219 ly_print(out, "%*s\"%s\":", LEVEL, INDENT, node->schema->name);
Michal Vasko98763c62015-07-17 13:47:00 +0200220 }
221
Radek Krejci23238922015-10-27 17:13:34 +0100222 if (flag_empty) {
Michal Vasko95068c42016-03-24 14:58:11 +0100223 ly_print(out, "%snull", (level ? " " : ""));
Radek Krejci23238922015-10-27 17:13:34 +0100224 return;
225 }
Michal Vasko95068c42016-03-24 14:58:11 +0100226 ly_print(out, "%s[%s", (level ? " " : ""), (level ? "\n" : ""));
Radek Krejci23238922015-10-27 17:13:34 +0100227
Michal Vasko95068c42016-03-24 14:58:11 +0100228 if (!is_list && level) {
Michal Vasko98763c62015-07-17 13:47:00 +0200229 ++level;
230 }
Radek Krejci27aaa732015-09-04 15:24:04 +0200231
232 while (list) {
Michal Vasko98763c62015-07-17 13:47:00 +0200233 if (is_list) {
Radek Krejci27aaa732015-09-04 15:24:04 +0200234 /* list print */
Michal Vasko95068c42016-03-24 14:58:11 +0100235 if (level) {
236 ++level;
237 }
238 ly_print(out, "%*s{%s", LEVEL, INDENT, (level ? "\n" : ""));
239 if (level) {
240 ++level;
241 }
Radek Krejcida61fb22015-10-30 11:10:03 +0100242 if (list->attr) {
Michal Vasko95068c42016-03-24 14:58:11 +0100243 ly_print(out, "%*s\"@\":%s{%s", LEVEL, INDENT, (level ? " " : ""), (level ? "\n" : ""));
严军喜100794898b539cf2016-10-12 16:34:52 +0800244 json_print_attrs(out, level + 1, list, NULL);
Radek Krejcida61fb22015-10-30 11:10:03 +0100245 ly_print(out, "%*s}%s", LEVEL, INDENT, list->child ? ",\n" : "");
246 }
Radek Krejci46180b52016-08-31 16:01:32 +0200247 json_print_nodes(out, level, list->child, 1, 0, options);
Michal Vasko95068c42016-03-24 14:58:11 +0100248 if (level) {
249 --level;
250 }
Radek Krejci76b07902015-10-09 09:11:25 +0200251 ly_print(out, "%*s}", LEVEL, INDENT);
Michal Vasko95068c42016-03-24 14:58:11 +0100252 if (level) {
253 --level;
254 }
Michal Vasko98763c62015-07-17 13:47:00 +0200255 } else {
Radek Krejci27aaa732015-09-04 15:24:04 +0200256 /* leaf-list print */
Radek Krejci76b07902015-10-09 09:11:25 +0200257 ly_print(out, "%*s", LEVEL, INDENT);
Radek Krejci46180b52016-08-31 16:01:32 +0200258 json_print_leaf(out, level, list, 1, toplevel, options);
Radek Krejcida61fb22015-10-30 11:10:03 +0100259 if (list->attr) {
260 flag_attrs = 1;
261 }
Radek Krejci27aaa732015-09-04 15:24:04 +0200262 }
263 for (list = list->next; list && list->schema != node->schema; list = list->next);
264 if (list) {
Michal Vasko95068c42016-03-24 14:58:11 +0100265 ly_print(out, ",%s", (level ? "\n" : ""));
Michal Vasko98763c62015-07-17 13:47:00 +0200266 }
267 }
Radek Krejci27aaa732015-09-04 15:24:04 +0200268
Michal Vasko95068c42016-03-24 14:58:11 +0100269 if (!is_list && level) {
Michal Vasko98763c62015-07-17 13:47:00 +0200270 --level;
271 }
272
Michal Vasko95068c42016-03-24 14:58:11 +0100273 ly_print(out, "%s%*s]", (level ? "\n" : ""), LEVEL, INDENT);
Radek Krejcida61fb22015-10-30 11:10:03 +0100274
275 /* attributes */
276 if (!is_list && flag_attrs) {
277 if (schema) {
Michal Vasko95068c42016-03-24 14:58:11 +0100278 ly_print(out, ",%s%*s\"@%s:%s\":%s[%s", (level ? "\n" : ""), LEVEL, INDENT, schema, node->schema->name,
279 (level ? " " : ""), (level ? "\n" : ""));
Radek Krejcida61fb22015-10-30 11:10:03 +0100280 } else {
Michal Vasko95068c42016-03-24 14:58:11 +0100281 ly_print(out, ",%s%*s\"@%s\":%s[%s", (level ? "\n" : ""), LEVEL, INDENT, node->schema->name,
282 (level ? " " : ""), (level ? "\n" : ""));
Radek Krejcida61fb22015-10-30 11:10:03 +0100283 }
Michal Vasko95068c42016-03-24 14:58:11 +0100284 if (level) {
285 level++;
286 }
Radek Krejcida61fb22015-10-30 11:10:03 +0100287 for (list = node; list; ) {
288 if (list->attr) {
Michal Vasko95068c42016-03-24 14:58:11 +0100289 ly_print(out, "%*s{%s", LEVEL, INDENT, (level ? " " : ""));
Radek Krejci1eefeb32016-04-15 16:01:46 +0200290 json_print_attrs(out, 0, list, NULL);
Radek Krejcida61fb22015-10-30 11:10:03 +0100291 ly_print(out, "%*s}", LEVEL, INDENT);
292 } else {
293 ly_print(out, "%*snull", LEVEL, INDENT);
294 }
295
296
297 for (list = list->next; list && list->schema != node->schema; list = list->next);
298 if (list) {
Michal Vasko95068c42016-03-24 14:58:11 +0100299 ly_print(out, ",%s", (level ? "\n" : ""));
Radek Krejcida61fb22015-10-30 11:10:03 +0100300 }
301 }
Michal Vasko95068c42016-03-24 14:58:11 +0100302 if (level) {
303 level--;
304 }
305 ly_print(out, "%s%*s]", (level ? "\n" : ""), LEVEL, INDENT);
Radek Krejcida61fb22015-10-30 11:10:03 +0100306 }
Michal Vasko98763c62015-07-17 13:47:00 +0200307}
308
309static void
Radek Krejci46180b52016-08-31 16:01:32 +0200310json_print_anydata(struct lyout *out, int level, const struct lyd_node *node, int toplevel, int options)
Michal Vaskoab8e4402015-07-17 12:54:28 +0200311{
Radek Krejcida61fb22015-10-30 11:10:03 +0100312 const char *schema = NULL;
Radek Krejcibf2abff2016-08-23 15:51:52 +0200313 struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
Radek Krejcida61fb22015-10-30 11:10:03 +0100314
Michal Vasko635bd452016-05-18 13:26:55 +0200315 if (toplevel || !node->parent || nscmp(node, node->parent)) {
Radek Krejcida61fb22015-10-30 11:10:03 +0100316 /* print "namespace" */
Michal Vasko6c629ac2016-02-15 14:08:23 +0100317 schema = lys_node_module(node->schema)->name;
Radek Krejci4ae82942016-09-19 16:41:06 +0200318 ly_print(out, "%*s\"%s:%s\":%s{%s", LEVEL, INDENT, schema, node->schema->name, (level ? " " : ""), (level ? "\n" : ""));
Radek Krejcida61fb22015-10-30 11:10:03 +0100319 } else {
Radek Krejci4ae82942016-09-19 16:41:06 +0200320 ly_print(out, "%*s\"%s\":%s{%s", LEVEL, INDENT, node->schema->name, (level ? " " : ""), (level ? "\n" : ""));
321 }
322 if (level) {
323 level++;
Radek Krejci9a5daea2016-03-02 16:49:40 +0100324 }
325
Radek Krejci4ae82942016-09-19 16:41:06 +0200326 switch (any->value_type) {
327 case LYD_ANYDATA_DATATREE:
328 json_print_nodes(out, level, any->value.tree, 1, 0, options);
329 break;
330 case LYD_ANYDATA_JSON:
331 if (any->value.str) {
332 ly_print(out, "%*s%s\n", LEVEL, INDENT, any->value.str);
Radek Krejci9a5daea2016-03-02 16:49:40 +0100333 }
Radek Krejci4ae82942016-09-19 16:41:06 +0200334 break;
335 default:
336 /* other formats are not supported */
337 LOGWRN("Unable to print anydata content (type %d) as JSON.", any->value_type);
338 break;
Radek Krejcida61fb22015-10-30 11:10:03 +0100339 }
340
341 /* print attributes as sibling leaf */
342 if (node->attr) {
Radek Krejcida61fb22015-10-30 11:10:03 +0100343 if (schema) {
Radek Krejci88f29302015-10-30 15:42:33 +0100344 ly_print(out, ",\n%*s\"@%s:%s\": {\n", LEVEL, INDENT, schema, node->schema->name);
Radek Krejcida61fb22015-10-30 11:10:03 +0100345 } else {
Radek Krejci88f29302015-10-30 15:42:33 +0100346 ly_print(out, ",\n%*s\"@%s\": {\n", LEVEL, INDENT, node->schema->name);
Radek Krejcida61fb22015-10-30 11:10:03 +0100347 }
Radek Krejci1eefeb32016-04-15 16:01:46 +0200348 json_print_attrs(out, (level ? level + 1 : level), node, NULL);
Radek Krejcida61fb22015-10-30 11:10:03 +0100349 ly_print(out, "%*s}", LEVEL, INDENT);
350 }
Radek Krejci4ae82942016-09-19 16:41:06 +0200351
352
353 if (level) {
354 level--;
355 }
356 ly_print(out, "%*s}", LEVEL, INDENT);
Michal Vaskoab8e4402015-07-17 12:54:28 +0200357}
358
Radek Krejci5044be32016-01-18 17:05:51 +0100359static void
Radek Krejci46180b52016-08-31 16:01:32 +0200360json_print_nodes(struct lyout *out, int level, const struct lyd_node *root, int withsiblings, int toplevel, int options)
Radek Krejci94ca54b2015-07-08 15:48:47 +0200361{
Radek Krejci572f1222016-09-01 09:52:47 +0200362 const struct lyd_node *node, *iter;
Radek Krejci27aaa732015-09-04 15:24:04 +0200363
364 LY_TREE_FOR(root, node) {
Radek Krejci572f1222016-09-01 09:52:47 +0200365 if (!lyd_wd_toprint(node, options)) {
366 continue;
Radek Krejci46180b52016-08-31 16:01:32 +0200367 }
368
Radek Krejci27aaa732015-09-04 15:24:04 +0200369 switch (node->schema->nodetype) {
Radek Krejcifb54be42015-10-02 15:21:16 +0200370 case LYS_RPC:
Michal Vaskoafa7a642016-10-18 15:11:38 +0200371 case LYS_ACTION:
Radek Krejcifb54be42015-10-02 15:21:16 +0200372 case LYS_NOTIF:
Radek Krejci27aaa732015-09-04 15:24:04 +0200373 case LYS_CONTAINER:
374 if (node->prev->next) {
375 /* print the previous comma */
Michal Vasko95068c42016-03-24 14:58:11 +0100376 ly_print(out, ",%s", (level ? "\n" : ""));
Radek Krejci27aaa732015-09-04 15:24:04 +0200377 }
Radek Krejci46180b52016-08-31 16:01:32 +0200378 json_print_container(out, level, node, toplevel, options);
Radek Krejci27aaa732015-09-04 15:24:04 +0200379 break;
380 case LYS_LEAF:
381 if (node->prev->next) {
382 /* print the previous comma */
Michal Vasko95068c42016-03-24 14:58:11 +0100383 ly_print(out, ",%s", (level ? "\n" : ""));
Radek Krejci27aaa732015-09-04 15:24:04 +0200384 }
Radek Krejci46180b52016-08-31 16:01:32 +0200385 json_print_leaf(out, level, node, 0, toplevel, options);
Radek Krejci27aaa732015-09-04 15:24:04 +0200386 break;
387 case LYS_LEAFLIST:
388 case LYS_LIST:
389 /* is it already printed? */
Radek Krejci9ce61512015-10-26 14:42:32 +0100390 for (iter = node->prev; iter->next; iter = iter->prev) {
Radek Krejci27aaa732015-09-04 15:24:04 +0200391 if (iter == node) {
392 continue;
393 }
394 if (iter->schema == node->schema) {
395 /* the list has alread some previous instance and therefore it is already printed */
396 break;
397 }
398 }
Michal Vasko6c563772015-10-15 10:49:30 +0200399 if (!iter->next) {
Radek Krejci27aaa732015-09-04 15:24:04 +0200400 if (node->prev->next) {
401 /* print the previous comma */
Michal Vasko95068c42016-03-24 14:58:11 +0100402 ly_print(out, ",%s", (level ? "\n" : ""));
Radek Krejci27aaa732015-09-04 15:24:04 +0200403 }
404
405 /* print the list/leaflist */
Radek Krejci46180b52016-08-31 16:01:32 +0200406 json_print_leaf_list(out, level, node, node->schema->nodetype == LYS_LIST ? 1 : 0, toplevel, options);
Radek Krejci27aaa732015-09-04 15:24:04 +0200407 }
408 break;
409 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200410 case LYS_ANYDATA:
Radek Krejci27aaa732015-09-04 15:24:04 +0200411 if (node->prev->next) {
412 /* print the previous comma */
Michal Vasko95068c42016-03-24 14:58:11 +0100413 ly_print(out, ",%s", (level ? "\n" : ""));
Radek Krejci27aaa732015-09-04 15:24:04 +0200414 }
Radek Krejci46180b52016-08-31 16:01:32 +0200415 json_print_anydata(out, level, node, toplevel, options);
Radek Krejci27aaa732015-09-04 15:24:04 +0200416 break;
417 default:
418 LOGINT;
419 break;
420 }
Radek Krejci5044be32016-01-18 17:05:51 +0100421
422 if (!withsiblings) {
423 break;
424 }
Radek Krejci94ca54b2015-07-08 15:48:47 +0200425 }
Radek Krejci4ae82942016-09-19 16:41:06 +0200426 if (root && level) {
Michal Vasko95068c42016-03-24 14:58:11 +0100427 ly_print(out, "\n");
428 }
Radek Krejci94ca54b2015-07-08 15:48:47 +0200429}
430
Radek Krejcif3752b02015-10-02 15:31:34 +0200431int
Radek Krejci5044be32016-01-18 17:05:51 +0100432json_print_data(struct lyout *out, const struct lyd_node *root, int options)
Radek Krejci94ca54b2015-07-08 15:48:47 +0200433{
Michal Vaskoafa7a642016-10-18 15:11:38 +0200434 const struct lyd_node *node, *next;
435 int level = 0, action_input = 0;
Radek Krejci94ca54b2015-07-08 15:48:47 +0200436
Michal Vasko95068c42016-03-24 14:58:11 +0100437 if (options & LYP_FORMAT) {
438 ++level;
439 }
440
Michal Vaskoafa7a642016-10-18 15:11:38 +0200441 if (options & LYP_NETCONF) {
442 if (root->schema->nodetype != LYS_RPC) {
443 /* learn whether we are printing an action */
444 LY_TREE_DFS_BEGIN(root, next, node) {
445 if (node->schema->nodetype == LYS_ACTION) {
446 break;
447 }
448 LY_TREE_DFS_END(root, next, node);
449 }
450 } else {
451 node = root;
452 }
453
454 if (node && (node->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
455 if (node->child && (node->child->schema->parent->nodetype == LYS_OUTPUT)) {
456 /* skip the container */
457 root = node->child;
458 } else if (node->schema->nodetype == LYS_ACTION) {
459 action_input = 1;
460 }
461 }
462 }
463
Radek Krejci94ca54b2015-07-08 15:48:47 +0200464 /* start */
Michal Vasko95068c42016-03-24 14:58:11 +0100465 ly_print(out, "{%s", (level ? "\n" : ""));
Radek Krejci94ca54b2015-07-08 15:48:47 +0200466
Michal Vaskoafa7a642016-10-18 15:11:38 +0200467 if (action_input) {
468 ly_print(out, "%*s\"yang:action\":%s{%s", LEVEL, INDENT, (level ? " " : ""), (level ? "\n" : ""));
469 if (level) {
470 ++level;
471 }
472 }
473
Radek Krejci94ca54b2015-07-08 15:48:47 +0200474 /* content */
Radek Krejci46180b52016-08-31 16:01:32 +0200475 json_print_nodes(out, level, root, options & LYP_WITHSIBLINGS, 1, options);
Radek Krejci94ca54b2015-07-08 15:48:47 +0200476
Michal Vaskoafa7a642016-10-18 15:11:38 +0200477 if (action_input) {
478 if (level) {
479 --level;
480 }
481 ly_print(out, "%*s}%s", LEVEL, INDENT, (level ? "\n" : ""));
482 }
483
Radek Krejci94ca54b2015-07-08 15:48:47 +0200484 /* end */
Michal Vasko95068c42016-03-24 14:58:11 +0100485 ly_print(out, "}%s", (level ? "\n" : ""));
Radek Krejci94ca54b2015-07-08 15:48:47 +0200486
Michal Vaskoafa7a642016-10-18 15:11:38 +0200487 ly_print_flush(out);
Radek Krejci94ca54b2015-07-08 15:48:47 +0200488 return EXIT_SUCCESS;
489}