--- /dev/null	Tue Jan 29 00:40:57 2013
+++ new/usr/src/lib/libnvpair/nvpair_json.c	Tue Jan 29 00:40:57 2013
@@ -0,0 +1,367 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <strings.h>
+
+#include "libnvpair.h"
+
+/*
+ * When formatting a string for JSON output we must escape certain characters,
+ * as described in RFC4627.  This applies to both member names and
+ * DATA_TYPE_STRING values.
+ */
+static void
+nvlist_print_json_string(FILE *fp, const char *input)
+{
+	char c;
+
+	fprintf(fp, "\"");
+	while ((c = *input++) != '\0') {
+		switch (c) {
+		case '"':
+			fprintf(fp, "\\\"");
+			break;
+		case '\n':
+			fprintf(fp, "\\n");
+			break;
+		case '\r':
+			fprintf(fp, "\\r");
+			break;
+		case '\\':
+			fprintf(fp, "\\\\");
+			break;
+		case '\f':
+			fprintf(fp, "\\f");
+			break;
+		case '\t':
+			fprintf(fp, "\\t");
+			break;
+		case '\b':
+			fprintf(fp, "\\b");
+			break;
+		default:
+			if (c >= 0x00 && c <= 0x1f) {
+				fprintf(fp, "\\u00%02hhu", c);
+			} else {
+				fprintf(fp, "%c", c);
+			}
+			break;
+		}
+	}
+	fprintf(fp, "\"");
+}
+
+void
+nvlist_print_json(FILE *fp, nvlist_t *nvl)
+{
+	nvpair_t *curr;
+	boolean_t first = B_TRUE;
+
+	fprintf(fp, "{");
+
+	for (curr = nvlist_next_nvpair(nvl, NULL); curr;
+	    curr = nvlist_next_nvpair(nvl, curr)) {
+		data_type_t type = nvpair_type(curr);
+
+		if (!first)
+			fprintf(fp, ",");
+		else
+			first = B_FALSE;
+
+		nvlist_print_json_string(fp, nvpair_name(curr));
+		fprintf(fp, ":");
+
+		switch (type) {
+		case DATA_TYPE_STRING: {
+			char *string;
+			nvpair_value_string(curr, &string);
+			nvlist_print_json_string(fp, string);
+			break;
+		}
+
+		case DATA_TYPE_BOOLEAN: {
+			fprintf(fp, "true");
+			break;
+		}
+
+		case DATA_TYPE_BOOLEAN_VALUE: {
+			boolean_t boolean;
+			nvpair_value_boolean_value(curr, &boolean);
+			fprintf(fp, "%s", boolean == B_TRUE ? "true" :
+			    "false");
+			break;
+		}
+
+		case DATA_TYPE_BYTE: {
+			uchar_t val;
+			nvpair_value_byte(curr, &val);
+			fprintf(fp, "%hhu", val);
+			break;
+		}
+
+		case DATA_TYPE_INT8: {
+			int8_t val;
+			nvpair_value_int8(curr, &val);
+			fprintf(fp, "%hhd", val);
+			break;
+		}
+
+		case DATA_TYPE_UINT8: {
+			uint8_t val;
+			nvpair_value_uint8(curr, &val);
+			fprintf(fp, "%hhu", val);
+			break;
+		}
+
+		case DATA_TYPE_INT16: {
+			int16_t val;
+			nvpair_value_int16(curr, &val);
+			fprintf(fp, "%hd", val);
+			break;
+		}
+
+		case DATA_TYPE_UINT16: {
+			uint16_t val;
+			nvpair_value_uint16(curr, &val);
+			fprintf(fp, "%hu", val);
+			break;
+		}
+
+		case DATA_TYPE_INT32: {
+			int32_t val;
+			nvpair_value_int32(curr, &val);
+			fprintf(fp, "%d", val);
+			break;
+		}
+
+		case DATA_TYPE_UINT32: {
+			uint32_t val;
+			nvpair_value_uint32(curr, &val);
+			fprintf(fp, "%u", val);
+			break;
+		}
+
+		case DATA_TYPE_INT64: {
+			int64_t val;
+			nvpair_value_int64(curr, &val);
+			fprintf(fp, "%lld", val);
+			break;
+		}
+
+		case DATA_TYPE_UINT64: {
+			uint64_t val;
+			nvpair_value_uint64(curr, &val);
+			fprintf(fp, "%llu", val);
+			break;
+		}
+
+		case DATA_TYPE_HRTIME: {
+			hrtime_t val;
+			nvpair_value_hrtime(curr, &val);
+			fprintf(fp, "%llu", val);
+			break;
+		}
+
+		case DATA_TYPE_DOUBLE: {
+			double val;
+			nvpair_value_double(curr, &val);
+			fprintf(fp, "%f", val);
+			break;
+		}
+
+		case DATA_TYPE_NVLIST: {
+			nvlist_t *val;
+			nvpair_value_nvlist(curr, &val);
+			nvlist_print_json(fp, val);
+			break;
+		}
+
+		case DATA_TYPE_STRING_ARRAY: {
+			char **val;
+			uint_t valsz, pos;
+			nvpair_value_string_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				nvlist_print_json_string(fp, val[pos]);
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_NVLIST_ARRAY: {
+			nvlist_t **val;
+			uint_t valsz, pos;
+			nvpair_value_nvlist_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				nvlist_print_json(fp, val[pos]);
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_BOOLEAN_ARRAY: {
+			boolean_t *val;
+			uint_t valsz, pos;
+			nvpair_value_boolean_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				fprintf(fp, val[pos] == B_TRUE ?
+				    "true" : "false");
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_BYTE_ARRAY: {
+			uchar_t *val;
+			uint_t valsz, pos;
+			nvpair_value_byte_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				fprintf(fp, "%hhu", val[pos]);
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_UINT8_ARRAY: {
+			uint8_t *val;
+			uint_t valsz, pos;
+			nvpair_value_uint8_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				fprintf(fp, "%hhu", val[pos]);
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_INT8_ARRAY: {
+			int8_t *val;
+			uint_t valsz, pos;
+			nvpair_value_int8_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				fprintf(fp, "%hd", val[pos]);
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_UINT16_ARRAY: {
+			uint16_t *val;
+			uint_t valsz, pos;
+			nvpair_value_uint16_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				fprintf(fp, "%hu", val[pos]);
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_INT16_ARRAY: {
+			int16_t *val;
+			uint_t valsz, pos;
+			nvpair_value_int16_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				fprintf(fp, "%hhd", val[pos]);
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_UINT32_ARRAY: {
+			uint32_t *val;
+			uint_t valsz, pos;
+			nvpair_value_uint32_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				fprintf(fp, "%u", val[pos]);
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_INT32_ARRAY: {
+			int32_t *val;
+			uint_t valsz, pos;
+			nvpair_value_int32_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				fprintf(fp, "%d", val[pos]);
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_UINT64_ARRAY: {
+			uint64_t *val;
+			uint_t valsz, pos;
+			nvpair_value_uint64_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				fprintf(fp, "%llu", val[pos]);
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_INT64_ARRAY: {
+			int64_t *val;
+			uint_t valsz, pos;
+			nvpair_value_int64_array(curr, &val, &valsz);
+			fprintf(fp, "[");
+			for (pos = 0; pos < valsz; pos++) {
+				if (pos > 0)
+					fprintf(fp, ",");
+				fprintf(fp, "%lld", val[pos]);
+			}
+			fprintf(fp, "]");
+			break;
+		}
+
+		case DATA_TYPE_UNKNOWN:
+			fprintf(fp, "null");
+			break;
+		}
+	}
+
+	fprintf(fp, "}");
+}
