diff --git a/exec/load/json_lines.js b/exec/load/json_lines.js
new file mode 100644
index 0000000000000000000000000000000000000000..fb8c07c64a012aba59c20cf2fb4a28bdd0b89067
--- /dev/null
+++ b/exec/load/json_lines.js
@@ -0,0 +1,52 @@
+// $Id$
+
+// Library for dealing with "JSON Lines" (.jsonl)
+//                     and  "Newline Delimited JSON" (.ndjson) files
+
+"use strict";
+
+// Return true (success) or a string with an error
+function add(filename, obj)
+{
+	var f = new File(filename);
+	if(!f.open("a")) {
+		return "Error " + f.error + " opening " + filename;
+	}
+	f.writeln(JSON.stringify(obj));
+	f.close();
+	return true;
+}
+
+// Returns an array object on success, string on error
+// Pass a positive 'num' to return first num objects from file
+// Pass a negative 'num' to return last -num objects from file
+// If max_line_len == 0, default is 4096
+// Pass 'recover' value of true to ignore unparseable lines
+function get(filename, num, max_line_len, recover)
+{
+	var f = new File(filename);
+	if(!f.open("r", true)) {
+		return "Error " + f.error + " opening " + filename;
+	}
+	if(!max_line_len)
+		max_line_len = 4096;
+	var lines = f.readAll(max_line_len);
+	f.close();
+	if(num > 0)
+		lines = lines.slice(0, num);
+	else if(num < 0)
+		lines = lines.slice(num);
+	var list = [];
+	for(var i in lines) {
+		try {
+			var obj = JSON.parse(lines[i]);
+			list.push(obj);
+		} catch(e) {
+			if(!recover)
+				return e + " line " + (Number(i) + 1) + " of " + filename;
+		}
+	}
+	return list;
+}
+
+this;
\ No newline at end of file