diff --git a/util.h b/util.h
index d087cc6b33df511a316f9390eed4e9c187ba012c..898e5e17afbba86def6771d4c1b58679308b0dc5 100644
--- a/util.h
+++ b/util.h
@@ -24,4 +24,4 @@ char *jenter(char *s);
 char *jnext(char *s);
 char *jvalue(char *s);
 char *jlookup(char *s, char *key);
-
+char *jescape(char *s);
diff --git a/util/json.c b/util/json.c
index 9fb84e276846e97683168730b10c548b62bc96a9..b9fa3dcf12bbeee6ee183f4a4eebf914dc663403 100644
--- a/util/json.c
+++ b/util/json.c
@@ -5,6 +5,9 @@
 
 #include "../util.h"
 
+static char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+	'A', 'B', 'C', 'D', 'E', 'F'};
+
 static char *skip_ws(char *s)
 {
 	for (; *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'; s ++);
@@ -210,3 +213,41 @@ char *jlookup(char *s, char *key)
 			return jvalue(s);
 	return 0;
 }
+
+char *jescape(char *s)
+{
+	int i;
+	static __thread char buf[JSTR_SIZE];
+	for (i = 0; *s && i+7 < sizeof(buf); s ++)
+		switch (*s)
+		{
+			case '"':
+				buf[i ++] = '\\'; buf[i ++] = '"'; break;
+			case '\\':
+				buf[i ++] = '\\'; buf[i ++] = '\\'; break;
+			case '\b':
+				buf[i ++] = '\\'; buf[i ++] = 'b'; break;
+			case '\f':
+				buf[i ++] = '\\'; buf[i ++] = 'f'; break;
+			case '\n':
+				buf[i ++] = '\\'; buf[i ++] = 'n'; break;
+			case '\r':
+				buf[i ++] = '\\'; buf[i ++] = 'r'; break;
+			case '\t':
+				buf[i ++] = '\\'; buf[i ++] = 't'; break;
+			default:
+				if (*s <= 0x1f)
+				{
+					buf[i ++] = '\\';
+					buf[i ++] = 'u';
+					buf[i ++] = '0';
+					buf[i ++] = '0';
+					buf[i ++] = hex[*s >> 4];
+					buf[i ++] = hex[*s & 0xf];
+				}
+				else
+					buf[i ++] = *s;
+		}
+	buf[i] = 0;
+	return buf;
+}