1 /**
2 	JSON serialization and value handling.
3 
4 	This module provides the Json struct for reading, writing and manipulating
5 	JSON values. De(serialization) of arbitrary D types is also supported and
6 	is recommended for handling JSON in performance sensitive applications.
7 
8 	Copyright: © 2012-2015 Sönke Ludwig
9 	License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
10 	Authors: Sönke Ludwig
11 */
12 module vibe.data.json;
13 
14 ///
15 @safe unittest {
16 	void manipulateJson(Json j)
17 	{
18 		import std.stdio;
19 
20 		// retrieving the values is done using get()
21 		assert(j["name"].get!string == "Example");
22 		assert(j["id"].get!int == 1);
23 
24 		// semantic conversions can be done using to()
25 		assert(j["id"].to!string == "1");
26 
27 		// prints:
28 		// name: "Example"
29 		// id: 1
30 		foreach (key, value; j.byKeyValue)
31 			writefln("%s: %s", key, value);
32 
33 		// print out as JSON: {"name": "Example", "id": 1}
34 		writefln("JSON: %s", j.toString());
35 
36 		// DEPRECATED: object members can be accessed using member syntax, just like in JavaScript
37 		//j = Json.emptyObject;
38 		//j.name = "Example";
39 		//j.id = 1;
40 	}
41 }
42 
43 /// Constructing `Json` objects
44 @safe unittest {
45 	// construct a JSON object {"field1": "foo", "field2": 42, "field3": true}
46 
47 	// using the constructor
48 	Json j1 = Json(["field1": Json("foo"), "field2": Json(42), "field3": Json(true)]);
49 
50 	// using piecewise construction
51 	Json j2 = Json.emptyObject;
52 	j2["field1"] = "foo";
53 	j2["field2"] = 42.0;
54 	j2["field3"] = true;
55 
56 	// using serialization
57 	struct S {
58 		string field1;
59 		double field2;
60 		bool field3;
61 	}
62 	Json j3 = S("foo", 42, true).serializeToJson();
63 
64 	// using serialization, converting directly to a JSON string
65 	string j4 = S("foo", 32, true).serializeToJsonString();
66 }
67 
68 
69 public import vibe.data.serialization;
70 public import std.json : JSONException;
71 
72 import vibe.internal.conv : enumToString;
73 
74 import std.algorithm;
75 import std.array;
76 import std.bigint;
77 import std.conv;
78 import std.datetime;
79 import std.exception;
80 import std.format;
81 import std.json : JSONValue, JSONType;
82 import std.range;
83 import std.string;
84 import std.traits;
85 import std.typecons : Tuple;
86 import std.uuid;
87 
88 /******************************************************************************/
89 /* public types                                                               */
90 /******************************************************************************/
91 
92 /**
93 	Represents a single JSON value.
94 
95 	Json values can have one of the types defined in the Json.Type enum. They
96 	behave mostly like values in ECMA script in the way that you can
97 	transparently perform operations on them. However, strict typechecking is
98 	done, so that operations between differently typed JSON values will throw
99 	a JSONException. Additionally, an explicit cast or using get!() or to!() is
100 	required to convert a JSON value to the corresponding static D type.
101 */
102 struct Json {
103 @safe:
104 
105 	static assert(!hasElaborateDestructor!BigInt && !hasElaborateCopyConstructor!BigInt,
106 		"struct Json is missing required ~this and/or this(this) members for BigInt.");
107 
108 	private {
109 		union {
110 			BigInt m_bigInt;
111 			long m_int;
112 			double m_float;
113 			bool m_bool;
114 			string m_string;
115 			Json[string] m_object;
116 			Json[] m_array;
117 			FillerType m_filler;
118 		}
119 
120 		Type m_type = Type.undefined;
121 
122 		version (VibeJsonFieldNames) {
123 			string m_name;
124 		}
125 	}
126 
127 	// we should just use ubyte[exactSize] in the union,
128 	// but using a static array there breaks ctfe.
129 	// so just replace it with a struct with enough fields to cover every other type.
130 	// Note that this will round Json's size to the nearest word-size,
131 	// but that's okay because we want to be word aligned anyways.
132 	private struct FillerType
133 	{
134 		static import std.meta;
135 
136 		enum exactSize = Largest!(BigInt, long, double, bool, string, Json[string], Json[]).sizeof;
137 		enum numFields = (exactSize + size_t.sizeof - 1) / size_t.sizeof;
138 
139 		std.meta.Repeat!(numFields, size_t) fields;
140 	}
141 
142 	/** Represents the run time type of a JSON value.
143 	*/
144 	enum Type {
145 		undefined,  /// A non-existent value in a JSON object
146 		null_,      /// Null value
147 		bool_,      /// Boolean value
148 		int_,       /// 64-bit integer value
149 		bigInt,     /// BigInt values
150 		float_,     /// 64-bit floating point value
151 		string,     /// UTF-8 string
152 		array,      /// Array of JSON values
153 		object,     /// JSON object aka. dictionary from string to Json
154 
155 		deprecated("Use `undefined` instead.") Undefined = undefined,  /// Compatibility alias
156 		deprecated("Use `null_` instead.") Null = null_,           /// Compatibility alias
157 		deprecated("Use `bool_` instead.") Bool = bool_,           /// Compatibility alias
158 		deprecated("Use `int_` instead.") Int = int_,             /// Compatibility alias
159 		deprecated("Use `float_` instead.") Float = float_,         /// Compatibility alias
160 		deprecated("Use `string` instead.") String = string,        /// Compatibility alias
161 		deprecated("Use `array` instead.") Array = array,          /// Compatibility alias
162 		deprecated("Use `object` instead.") Object = object         /// Compatibility alias
163 	}
164 
165 	/// New JSON value of Type.Undefined
166 	static @property Json undefined() nothrow { return Json(); }
167 
168 	/// New JSON value of Type.Object
169 	static @property Json emptyObject() nothrow { return Json(cast(Json[string])null); }
170 
171 	/// New JSON value of Type.Array
172 	static @property Json emptyArray() nothrow { return Json(cast(Json[])null); }
173 
174 	version(JsonLineNumbers) int line;
175 
176 	/**
177 		Constructor for a JSON object.
178 	*/
179 	this(typeof(null)) nothrow { zeroFields; m_type = Type.null_; }
180 	/// ditto
181 	this(bool v) nothrow { zeroFields; m_type = Type.bool_; m_bool = v; }
182 	/// ditto
183 	this(byte v) nothrow { this(cast(long)v); }
184 	/// ditto
185 	this(ubyte v) nothrow { this(cast(long)v); }
186 	/// ditto
187 	this(short v) nothrow { this(cast(long)v); }
188 	/// ditto
189 	this(ushort v) nothrow { this(cast(long)v); }
190 	/// ditto
191 	this(int v) nothrow { this(cast(long)v); }
192 	/// ditto
193 	this(uint v) nothrow { this(cast(long)v); }
194 	/// ditto
195 	this(long v) nothrow { zeroFields; m_type = Type.int_; m_int = v; }
196 	/// ditto
197 	this(BigInt v) nothrow @trusted { zeroFields; m_type = Type.bigInt; initBigInt(); m_bigInt = v; }
198 	/// ditto
199 	this(double v) nothrow { zeroFields; m_type = Type.float_; m_float = v; }
200 	/// ditto
201 	this(string v) nothrow @trusted { zeroFields; m_type = Type..string; m_string = v; }
202 	/// ditto
203 	this(Json[] v) nothrow @trusted { zeroFields; m_type = Type.array; m_array = v; }
204 	/// ditto
205 	this(Json[string] v) nothrow @trusted { zeroFields; m_type = Type.object; m_object = v; }
206 
207 	// used internally for UUID serialization support
208 	private this(UUID v) nothrow { this(v.toString()); }
209 
210 	// ensure that stale pointers in unused union memory don't cause leaks
211 	private void zeroFields() nothrow { m_filler = FillerType.init; }
212 
213 	/**
214 		Converts a std.json.JSONValue object to a vibe Json object.
215 	 */
216 	this(in JSONValue value) {
217 		final switch (value.type) {
218 			case JSONType.null_: this = null; break;
219 			case JSONType.object:
220 				this = emptyObject;
221 				() @trusted {
222 					foreach (string k, ref const JSONValue v; value.object)
223 						this[k] = Json(v);
224 				} ();
225 				break;
226 			case JSONType.array:
227 				this = (() @trusted => Json(value.array.map!(a => Json(a)).array))();
228 				break;
229 			case JSONType..string: this = value.str; break;
230 			case JSONType.integer: this = value.integer; break;
231 			case JSONType.uinteger: this = BigInt(value.uinteger); break;
232 			case JSONType.float_: this = value.floating; break;
233 			case JSONType.true_: this = true; break;
234 			case JSONType.false_: this = false; break;
235 		}
236 	}
237 
238 
239 	/**
240 		Allows assignment of D values to a JSON value.
241 	*/
242 	ref Json opAssign(Json v) return @trusted
243 	nothrow {
244 		if (v.type != Type.bigInt)
245 			runDestructors();
246 		auto old_type = m_type;
247 		m_type = v.m_type;
248 		final switch(m_type){
249 			case Type.undefined: m_string = null; break;
250 			case Type.null_: m_string = null; break;
251 			case Type.bool_: m_bool = v.m_bool; break;
252 			case Type.int_: m_int = v.m_int; break;
253 			case Type.bigInt:
254 				if (old_type != Type.bigInt)
255 					initBigInt();
256 				m_bigInt = v.m_bigInt;
257 				break;
258 			case Type.float_: m_float = v.m_float; break;
259 			case Type..string: m_string = v.m_string; break;
260 			case Type.array: opAssign(v.m_array); break;
261 			case Type.object: opAssign(v.m_object); break;
262 		}
263 		return this;
264 	}
265 	/// ditto
266 	void opAssign(typeof(null)) nothrow @trusted { runDestructors(); m_type = Type.null_; m_string = null; }
267 	/// ditto
268 	bool opAssign(bool v) nothrow { runDestructors(); m_type = Type.bool_; m_bool = v; return v; }
269 	/// ditto
270 	int opAssign(int v) nothrow { runDestructors(); m_type = Type.int_; m_int = v; return v; }
271 	/// ditto
272 	long opAssign(long v) nothrow { runDestructors(); m_type = Type.int_; m_int = v; return v; }
273 	/// ditto
274 	BigInt opAssign(BigInt v)
275 	nothrow @trusted {
276 		if (m_type != Type.bigInt)
277 			initBigInt();
278 		m_type = Type.bigInt;
279 		m_bigInt = v;
280 		return v;
281 	}
282 	/// ditto
283 	double opAssign(double v) nothrow { runDestructors(); m_type = Type.float_; m_float = v; return v; }
284 	/// ditto
285 	string opAssign(string v) nothrow @trusted { runDestructors(); m_type = Type..string; m_string = v; return v; }
286 	/// ditto
287 	Json[] opAssign(Json[] v)
288 	nothrow @trusted {
289 		runDestructors();
290 		m_type = Type.array;
291 		m_array = v;
292 		version (VibeJsonFieldNames) {
293 			try {
294 				foreach (idx, ref av; m_array)
295 					av.m_name = format("%s[%s]", m_name, idx);
296 			} catch (Exception e) assert(false, e.msg);
297 		}
298 		return v;
299 	}
300 	/// ditto
301 	Json[string] opAssign(Json[string] v)
302 	nothrow @trusted {
303 		runDestructors();
304 		m_type = Type.object;
305 		m_object = v;
306 		version (VibeJsonFieldNames) {
307 			try {
308 				foreach (key, ref av; m_object)
309 					av.m_name = format("%s.%s", m_name, key);
310 			} catch (Exception e) assert(false, e.msg);
311 		}
312 		return v;
313 	}
314 
315 	// used internally for UUID serialization support
316 	private UUID opAssign(UUID v) nothrow { opAssign(v.toString()); return v; }
317 
318 	/**
319 		Allows removal of values from Type.Object Json objects.
320 	*/
321 	void remove(string item) @trusted { checkType!(Json[string])(); m_object.remove(item); }
322 
323 	/**
324 		The current type id of this JSON object.
325 	*/
326 	@property Type type() const nothrow { return m_type; }
327 
328 	/**
329 		Clones a JSON value recursively.
330 	*/
331 	Json clone()
332 	const nothrow @trusted {
333 		final switch (m_type) {
334 			case Type.undefined: return Json.undefined;
335 			case Type.null_: return Json(null);
336 			case Type.bool_: return Json(m_bool);
337 			case Type.int_: return Json(m_int);
338 			case Type.bigInt: return Json(m_bigInt);
339 			case Type.float_: return Json(m_float);
340 			case Type..string: return Json(m_string);
341 			case Type.array:
342 				Json[] ret;
343 				foreach (v; m_array) ret ~= v.clone();
344 				return Json(ret);
345 			case Type.object:
346 				Json[string] ret;
347 				foreach (kv; m_object.byKeyValue)
348 					ret[kv.key] = kv.value.clone();
349 				return Json(ret);
350 		}
351 	}
352 
353 	/**
354 		Allows direct indexing of array typed JSON values.
355 	*/
356 	ref inout(Json) opIndex(size_t idx) inout @trusted { checkType!(Json[])(); return m_array[idx]; }
357 
358 	///
359 	@safe unittest {
360 		Json value = Json.emptyArray;
361 		value ~= 1;
362 		value ~= true;
363 		value ~= "foo";
364 		assert(value[0] == 1);
365 		assert(value[1] == true);
366 		assert(value[2] == "foo");
367 	}
368 
369 
370 	/**
371 		Allows direct indexing of object typed JSON values using a string as
372 		the key.
373 
374 		Returns an object of `Type.undefined` if the key was not found.
375 	*/
376 	const(Json) opIndex(string key)
377 	const @trusted {
378 		checkType!(Json[string])();
379 		if( auto pv = key in m_object ) return *pv;
380 		Json ret = Json.undefined;
381 		ret.m_string = key;
382 		version (VibeJsonFieldNames) ret.m_name = format("%s.%s", m_name, key);
383 		return ret;
384 	}
385 	/// ditto
386 	ref Json opIndex(string key)
387 	@trusted {
388 		checkType!(Json[string])();
389 		if( auto pv = key in m_object )
390 			return *pv;
391 		if (m_object is null) {
392 			m_object = ["": Json.init];
393 			m_object.remove("");
394 		}
395 		m_object[key] = Json.init;
396 		auto nv = key in m_object;
397 		assert(m_object !is null);
398 		assert(nv !is null, "Failed to insert key '"~key~"' into AA!?");
399 		nv.m_type = Type.undefined;
400 		assert(nv.type == Type.undefined);
401 		nv.m_string = key;
402 		version (VibeJsonFieldNames) nv.m_name = format("%s.%s", m_name, key);
403 		return *nv;
404 	}
405 
406 	///
407 	@safe unittest {
408 		Json value = Json.emptyObject;
409 		value["a"] = 1;
410 		value["b"] = true;
411 		value["c"] = "foo";
412 		assert(value["a"] == 1);
413 		assert(value["b"] == true);
414 		assert(value["c"] == "foo");
415 		assert(value["not-existing"].type() == Type.undefined);
416 	}
417 
418 	/**
419 		Returns a slice of a JSON array.
420 	*/
421 	inout(Json[]) opSlice()
422 	inout @trusted {
423 		checkType!(Json[])();
424 		return m_array;
425 	}
426 	///
427 	inout(Json[]) opSlice(size_t from, size_t to)
428 	inout @trusted {
429 		checkType!(Json[])();
430 		return m_array[from .. to];
431 	}
432 
433 	/**
434 		Returns the number of entries of string, array or object typed JSON values.
435 	*/
436 	@property size_t length()
437 	const @trusted {
438 		checkType!(string, Json[], Json[string])("property length");
439 		switch(m_type){
440 			case Type..string: return m_string.length;
441 			case Type.array: return m_array.length;
442 			case Type.object: return m_object.length;
443 			default: assert(false);
444 		}
445 	}
446 
447 	/**
448 		Allows foreach iterating over JSON objects and arrays.
449 	*/
450 	int opApply(scope int delegate(ref Json obj) del)
451 	@system {
452 		checkType!(Json[], Json[string])("opApply");
453 		if( m_type == Type.array ){
454 			foreach( ref v; m_array )
455 				if( auto ret = del(v) )
456 					return ret;
457 			return 0;
458 		} else {
459 			foreach( ref v; m_object )
460 				if( v.type != Type.undefined )
461 					if( auto ret = del(v) )
462 						return ret;
463 			return 0;
464 		}
465 	}
466 	/// ditto
467 	int opApply(scope int delegate(ref const Json obj) del)
468 	const @system {
469 		checkType!(Json[], Json[string])("opApply");
470 		if( m_type == Type.array ){
471 			foreach( ref v; m_array )
472 				if( auto ret = del(v) )
473 					return ret;
474 			return 0;
475 		} else {
476 			foreach( ref v; m_object )
477 				if( v.type != Type.undefined )
478 					if( auto ret = del(v) )
479 						return ret;
480 			return 0;
481 		}
482 	}
483 	/// ditto
484 	int opApply(scope int delegate(ref size_t idx, ref Json obj) del)
485 	@system {
486 		checkType!(Json[])("opApply");
487 		foreach( idx, ref v; m_array )
488 			if( auto ret = del(idx, v) )
489 				return ret;
490 		return 0;
491 	}
492 	/// ditto
493 	int opApply(scope int delegate(ref size_t idx, ref const Json obj) del)
494 	const @system {
495 		checkType!(Json[])("opApply");
496 		foreach( idx, ref v; m_array )
497 			if( auto ret = del(idx, v) )
498 				return ret;
499 		return 0;
500 	}
501 	/// ditto
502 	int opApply(scope int delegate(ref string idx, ref Json obj) del)
503 	@system {
504 		checkType!(Json[string])("opApply");
505 		foreach( idx, ref v; m_object )
506 			if( v.type != Type.undefined )
507 				if( auto ret = del(idx, v) )
508 					return ret;
509 		return 0;
510 	}
511 	/// ditto
512 	int opApply(scope int delegate(ref string idx, ref const Json obj) del)
513 	const @system {
514 		checkType!(Json[string])("opApply");
515 		foreach( idx, ref v; m_object )
516 			if( v.type != Type.undefined )
517 				if( auto ret = del(idx, v) )
518 					return ret;
519 		return 0;
520 	}
521 
522 	private alias KeyValue = Tuple!(string, "key", Json, "value");
523 
524 	/// Iterates over all key/value pairs of an object.
525 	@property auto byKeyValue()
526 	@trusted {
527 		checkType!(Json[string])("byKeyValue");
528 		return m_object.byKeyValue.map!(kv => KeyValue(kv.key, kv.value)).trustedRange;
529 	}
530 	/// ditto
531 	@property auto byKeyValue()
532 	const @trusted {
533 		checkType!(Json[string])("byKeyValue");
534 		return m_object.byKeyValue.map!(kv => const(KeyValue)(kv.key, kv.value)).trustedRange;
535 	}
536 	/// Iterates over all index/value pairs of an array.
537 	@property auto byIndexValue()
538 	@trusted {
539 		checkType!(Json[])("byIndexValue");
540 		return zip(iota(0, m_array.length), m_array);
541 	}
542 	/// ditto
543 	@property auto byIndexValue()
544 	const @trusted {
545 		checkType!(Json[])("byIndexValue");
546 		return zip(iota(0, m_array.length), m_array);
547 	}
548 	/// Iterates over all values of an object or array.
549 	@property auto byValue()
550 	@trusted {
551 		checkType!(Json[], Json[string])("byValue");
552 		static struct Rng {
553 			private {
554 				bool isArray;
555 				Json[] array;
556 				typeof(Json.init.m_object.byValue) object;
557 			}
558 
559 			bool empty() @trusted nothrow { if (isArray) return array.length == 0; else return object.empty; }
560 			auto front() @trusted nothrow { if (isArray) return array[0]; else return object.front; }
561 			void popFront() @trusted nothrow { if (isArray) array = array[1 .. $]; else object.popFront(); }
562 		}
563 
564 		if (m_type == Type.array) return Rng(true, m_array);
565 		else return Rng(false, null, m_object.byValue);
566 	}
567 	/// ditto
568 	@property auto byValue()
569 	const @trusted {
570 		checkType!(Json[], Json[string])("byValue");
571 		static struct Rng {
572 		@safe:
573 			private {
574 				bool isArray;
575 				const(Json)[] array;
576 				typeof(const(Json).init.m_object.byValue) object;
577 			}
578 
579 			bool empty() @trusted nothrow { if (isArray) return array.length == 0; else return object.empty; }
580 			auto front() @trusted nothrow { if (isArray) return array[0]; else return object.front; }
581 			void popFront() @trusted nothrow { if (isArray) array = array[1 .. $]; else object.popFront(); }
582 		}
583 
584 		if (m_type == Type.array) return Rng(true, m_array);
585 		else return Rng(false, null, m_object.byValue);
586 	}
587 
588 
589 	/**
590 		Converts this Json object to a std.json.JSONValue object
591 	 */
592 	T opCast(T)() const
593 		if (is(T == JSONValue))
594 	{
595 		final switch (type) {
596 			case Json.Type.undefined:
597 			case Json.Type.null_:
598 				return JSONValue(null);
599 			case Json.Type.bool_:
600 				return JSONValue(get!bool);
601 			case Json.Type.int_:
602 				return JSONValue(get!long);
603 			case Json.Type.bigInt:
604 				auto bi = get!BigInt;
605 				if (bi > long.max)
606 					return JSONValue((() @trusted => cast(ulong)get!BigInt)());
607 				else
608 					return JSONValue((() @trusted => cast(long)get!BigInt)());
609 			case Json.Type.float_:
610 				return JSONValue(get!double);
611 			case Json.Type..string:
612 				return JSONValue(get!string);
613 			case Json.Type.array:
614 				JSONValue[] ret;
615 				foreach (ref const Json e; byValue)
616 					ret ~= cast(JSONValue)e;
617 				return JSONValue(ret);
618 			case Json.Type.object:
619 				JSONValue[string] ret;
620 				foreach (string k, ref const Json e; byKeyValue) {
621 					if( e.type == Json.Type.undefined ) continue;
622 					ret[k] = cast(JSONValue)e;
623 				}
624 				return JSONValue(ret);
625 		}
626 	}
627 
628 
629 	/**
630 		Converts the JSON value to the corresponding D type - types must match exactly.
631 
632 		Available_Types:
633 			$(UL
634 				$(LI `bool` (`Type.bool_`))
635 				$(LI `double` (`Type.float_`))
636 				$(LI `float` (Converted from `double`))
637 				$(LI `long` (`Type.int_`))
638 				$(LI `ulong`, `int`, `uint`, `short`, `ushort`, `byte`, `ubyte` (Converted from `long`))
639 				$(LI `string` (`Type.string`))
640 				$(LI `Json[]` (`Type.array`))
641 				$(LI `Json[string]` (`Type.object`))
642 			)
643 
644 		See_Also: `opt`, `to`, `deserializeJson`
645 	*/
646 	inout(T) opCast(T)() inout if (!is(T == JSONValue)) { return get!T; }
647 	/// ditto
648 	@property inout(T) get(T)()
649 	inout @trusted {
650 		static if (!is(T : bool) && is(T : long))
651 			checkType!(long, BigInt)();
652 		else
653 			checkType!T();
654 
655 		static if (is(T == bool)) return m_bool;
656 		else static if (is(T == double)) return m_float;
657 		else static if (is(T == float)) return cast(T)m_float;
658 		else static if (is(T == string)) return m_string;
659 		else static if (is(T == UUID)) return UUID(m_string);
660 		else static if (is(T == Json[])) return m_array;
661 		else static if (is(T == Json[string])) return m_object;
662 		else static if (is(T == BigInt)) return m_type == Type.bigInt ? m_bigInt : BigInt(m_int);
663 		else static if (is(T : long)) {
664 			if (m_type == Type.bigInt) {
665 				enforceJson(m_bigInt <= T.max && m_bigInt >= T.min, "Integer conversion out of bounds error");
666 				return cast(T)m_bigInt.toLong();
667 			} else {
668 				enforceJson(m_int <= T.max && m_int >= T.min, "Integer conversion out of bounds error");
669 				return cast(T)m_int;
670 			}
671 		}
672 		else static assert(0, "JSON can only be cast to (bool, long, std.bigint.BigInt, double, string, Json[] or Json[string]. Not "~T.stringof~".");
673 	}
674 
675 	/**
676 		Returns the native type for this JSON if it matches the current runtime type.
677 
678 		If the runtime type does not match the given native type, the 'def' parameter is returned
679 		instead.
680 
681 		See_Also: `get`
682 	*/
683 	@property const(T) opt(T)(const(T) def = T.init)
684 	const {
685 		if( typeId!T != m_type ) return def;
686 		return get!T;
687 	}
688 	/// ditto
689 	@property T opt(T)(T def = T.init)
690 	{
691 		if( typeId!T != m_type ) return def;
692 		return get!T;
693 	}
694 
695 	/**
696 		Converts the JSON value to the corresponding D type - types are converted as necessary.
697 
698 		Automatically performs conversions between strings and numbers. See
699 		`get` for the list of available types. For converting/deserializing
700 		JSON to complex data types see `deserializeJson`.
701 
702 		See_Also: `get`, `deserializeJson`
703 	*/
704 	@property inout(T) to(T)()
705 	inout @trusted {
706 		static if( is(T == bool) ){
707 			final switch( m_type ){
708 				case Type.undefined: return false;
709 				case Type.null_: return false;
710 				case Type.bool_: return m_bool;
711 				case Type.int_: return m_int != 0;
712 				case Type.bigInt: return m_bigInt != 0;
713 				case Type.float_: return m_float != 0;
714 				case Type..string: return m_string.length > 0;
715 				case Type.array: return m_array.length > 0;
716 				case Type.object: return m_object.length > 0;
717 			}
718 		} else static if( is(T == double) ){
719 			final switch( m_type ){
720 				case Type.undefined: return T.init;
721 				case Type.null_: return 0;
722 				case Type.bool_: return m_bool ? 1 : 0;
723 				case Type.int_: return m_int;
724 				case Type.bigInt: return bigIntToLong();
725 				case Type.float_: return m_float;
726 				case Type..string: return .to!double(cast(string)m_string);
727 				case Type.array: return double.init;
728 				case Type.object: return double.init;
729 			}
730 		} else static if( is(T == float) ){
731 			final switch( m_type ){
732 				case Type.undefined: return T.init;
733 				case Type.null_: return 0;
734 				case Type.bool_: return m_bool ? 1 : 0;
735 				case Type.int_: return m_int;
736 				case Type.bigInt: return bigIntToLong();
737 				case Type.float_: return m_float;
738 				case Type..string: return .to!float(cast(string)m_string);
739 				case Type.array: return float.init;
740 				case Type.object: return float.init;
741 			}
742 		} else static if( is(T == long) ){
743 			final switch( m_type ){
744 				case Type.undefined: return 0;
745 				case Type.null_: return 0;
746 				case Type.bool_: return m_bool ? 1 : 0;
747 				case Type.int_: return m_int;
748 				case Type.bigInt: return cast(long)bigIntToLong();
749 				case Type.float_: return cast(long)m_float;
750 				case Type..string: return .to!long(m_string);
751 				case Type.array: return 0;
752 				case Type.object: return 0;
753 			}
754 		} else static if( is(T : long) ){
755 			final switch( m_type ){
756 				case Type.undefined: return 0;
757 				case Type.null_: return 0;
758 				case Type.bool_: return m_bool ? 1 : 0;
759 				case Type.int_: return cast(T)m_int;
760 				case Type.bigInt: return cast(T)bigIntToLong();
761 				case Type.float_: return cast(T)m_float;
762 				case Type..string: return cast(T).to!long(cast(string)m_string);
763 				case Type.array: return 0;
764 				case Type.object: return 0;
765 			}
766 		} else static if( is(T == string) ){
767 			switch( m_type ){
768 				default: return toString();
769 				case Type..string: return m_string;
770 			}
771 		} else static if( is(T == Json[]) ){
772 			switch( m_type ){
773 				default: return Json([this]);
774 				case Type.array: return m_array;
775 			}
776 		} else static if( is(T == Json[string]) ){
777 			switch( m_type ){
778 				default: return Json(["value": this]);
779 				case Type.object: return m_object;
780 			}
781 		} else static if( is(T == BigInt) ){
782 			final switch( m_type ){
783 				case Type.undefined: return BigInt(0);
784 				case Type.null_: return BigInt(0);
785 				case Type.bool_: return BigInt(m_bool ? 1 : 0);
786 				case Type.int_: return BigInt(m_int);
787 				case Type.bigInt: return m_bigInt;
788 				case Type.float_: return BigInt(cast(long)m_float);
789 				case Type..string: return BigInt(.to!long(m_string));
790 				case Type.array: return BigInt(0);
791 				case Type.object: return BigInt(0);
792 			}
793 		} else static if (is(T == JSONValue)) {
794 			return cast(JSONValue)this;
795 		} else static assert(0, "JSON can only be cast to (bool, long, std.bigint.BigInt, double, string, Json[] or Json[string]. Not "~T.stringof~".");
796 	}
797 
798 	/**
799 		Performs unary operations on the JSON value.
800 
801 		The following operations are supported for each type:
802 
803 		$(DL
804 			$(DT Null)   $(DD none)
805 			$(DT Bool)   $(DD ~)
806 			$(DT Int)    $(DD +, -, ++, --)
807 			$(DT Float)  $(DD +, -, ++, --)
808 			$(DT String) $(DD none)
809 			$(DT Array)  $(DD none)
810 			$(DT Object) $(DD none)
811 		)
812 	*/
813 	Json opUnary(string op)()
814 	const @trusted {
815 		static if( op == "~" ){
816 			checkType!bool();
817 			return Json(~m_bool);
818 		} else static if( op == "+" || op == "-" || op == "++" || op == "--" ){
819 			checkType!(BigInt, long, double)("unary "~op);
820 			if( m_type == Type.int_ ) mixin("return Json("~op~"m_int);");
821 			else if( m_type == Type.bigInt ) mixin("return Json("~op~"m_bigInt);");
822 			else if( m_type == Type.float_ ) mixin("return Json("~op~"m_float);");
823 			else assert(false);
824 		} else static assert(0, "Unsupported operator '"~op~"' for type JSON.");
825 	}
826 	/**
827 		Performs binary operations between JSON values.
828 
829 		The two JSON values must be of the same run time type or a JSONException
830 		will be thrown. Only the operations listed are allowed for each of the
831 		types.
832 
833 		$(DL
834 			$(DT Null)   $(DD none)
835 			$(DT Bool)   $(DD &&, ||)
836 			$(DT Int)    $(DD +, -, *, /, %)
837 			$(DT Float)  $(DD +, -, *, /, %)
838 			$(DT String) $(DD ~)
839 			$(DT Array)  $(DD ~)
840 			$(DT Object) $(DD in)
841 		)
842 	*/
843 	Json opBinary(string op)(ref const(Json) other)
844 	const @trusted {
845 		enforceJson(m_type == other.m_type, "Binary operation '"~op~"' between "~m_type.enumToString~" and "~other.m_type.enumToString~" JSON objects.");
846 		static if( op == "&&" ){
847 			checkType!(bool)(op);
848 			return Json(m_bool && other.m_bool);
849 		} else static if( op == "||" ){
850 			checkType!(bool)(op);
851 			return Json(m_bool || other.m_bool);
852 		} else static if( op == "+" ){
853 			checkType!(BigInt, long, double)(op);
854 			if( m_type == Type.int_ ) return Json(m_int + other.m_int);
855 			else if( m_type == Type.bigInt ) return Json(() @trusted { return m_bigInt + other.m_bigInt; } ());
856 			else if( m_type == Type.float_ ) return Json(m_float + other.m_float);
857 			else assert(false);
858 		} else static if( op == "-" ){
859 			checkType!(BigInt, long, double)(op);
860 			if( m_type == Type.int_ ) return Json(m_int - other.m_int);
861 			else if( m_type == Type.bigInt ) return Json(() @trusted { return m_bigInt - other.m_bigInt; } ());
862 			else if( m_type == Type.float_ ) return Json(m_float - other.m_float);
863 			else assert(false);
864 		} else static if( op == "*" ){
865 			checkType!(BigInt, long, double)(op);
866 			if( m_type == Type.int_ ) return Json(m_int * other.m_int);
867 			else if( m_type == Type.bigInt ) return Json(() @trusted { return m_bigInt * other.m_bigInt; } ());
868 			else if( m_type == Type.float_ ) return Json(m_float * other.m_float);
869 			else assert(false);
870 		} else static if( op == "/" ){
871 			checkType!(BigInt, long, double)(op);
872 			if( m_type == Type.int_ ) return Json(m_int / other.m_int);
873 			else if( m_type == Type.bigInt ) return Json(() @trusted { return m_bigInt / other.m_bigInt; } ());
874 			else if( m_type == Type.float_ ) return Json(m_float / other.m_float);
875 			else assert(false);
876 		} else static if( op == "%" ){
877 			checkType!(BigInt, long, double)(op);
878 			if( m_type == Type.int_ ) return Json(m_int % other.m_int);
879 			else if( m_type == Type.bigInt ) return Json(() @trusted { return m_bigInt % other.m_bigInt; } ());
880 			else if( m_type == Type.float_ ) return Json(m_float % other.m_float);
881 			else assert(false);
882 		} else static if( op == "~" ){
883 			checkType!(string, Json[])(op);
884 			if( m_type == Type..string ) return Json(m_string ~ other.m_string);
885 			else if (m_type == Type.array) return Json(m_array ~ other.m_array);
886 			else assert(false);
887 		} else static assert(0, "Unsupported operator '"~op~"' for type JSON.");
888 	}
889 	/// ditto
890 	Json opBinary(string op)(Json other) @trusted
891 		if( op == "~" )
892 	{
893 		static if( op == "~" ){
894 			checkType!(string, Json[])(op);
895 			if( m_type == Type..string ) return Json(m_string ~ other.m_string);
896 			else if( m_type == Type.array ) return Json(m_array ~ other.m_array);
897 			else assert(false);
898 		} else static assert(0, "Unsupported operator '"~op~"' for type JSON.");
899 	}
900 	/// ditto
901 	void opOpAssign(string op)(Json other) @trusted
902 		if (op == "+" || op == "-" || op == "*" || op == "/" || op == "%" || op =="~")
903 	{
904 		enforceJson(m_type == other.m_type || op == "~" && m_type == Type.array,
905 				"Binary operation '"~op~"=' between "~m_type.enumToString~" and "~other.m_type.enumToString~" JSON objects.");
906 		static if( op == "+" ){
907 			if( m_type == Type.int_ ) m_int += other.m_int;
908 			else if( m_type == Type.bigInt ) m_bigInt += other.m_bigInt;
909 			else if( m_type == Type.float_ ) m_float += other.m_float;
910 			else enforceJson(false, "'+=' only allowed for scalar types, not "~m_type.enumToString~".");
911 		} else static if( op == "-" ){
912 			if( m_type == Type.int_ ) m_int -= other.m_int;
913 			else if( m_type == Type.bigInt ) m_bigInt -= other.m_bigInt;
914 			else if( m_type == Type.float_ ) m_float -= other.m_float;
915 			else enforceJson(false, "'-=' only allowed for scalar types, not "~m_type.enumToString~".");
916 		} else static if( op == "*" ){
917 			if( m_type == Type.int_ ) m_int *= other.m_int;
918 			else if( m_type == Type.bigInt ) m_bigInt *= other.m_bigInt;
919 			else if( m_type == Type.float_ ) m_float *= other.m_float;
920 			else enforceJson(false, "'*=' only allowed for scalar types, not "~m_type.enumToString~".");
921 		} else static if( op == "/" ){
922 			if( m_type == Type.int_ ) m_int /= other.m_int;
923 			else if( m_type == Type.bigInt ) m_bigInt /= other.m_bigInt;
924 			else if( m_type == Type.float_ ) m_float /= other.m_float;
925 			else enforceJson(false, "'/=' only allowed for scalar types, not "~m_type.enumToString~".");
926 		} else static if( op == "%" ){
927 			if( m_type == Type.int_ ) m_int %= other.m_int;
928 			else if( m_type == Type.bigInt ) m_bigInt %= other.m_bigInt;
929 			else if( m_type == Type.float_ ) m_float %= other.m_float;
930 			else enforceJson(false, "'%=' only allowed for scalar types, not "~m_type.enumToString~".");
931 		} else static if( op == "~" ){
932 			if (m_type == Type..string) m_string ~= other.m_string;
933 			else if (m_type == Type.array) {
934 				if (other.m_type == Type.array) m_array ~= other.m_array;
935 				else appendArrayElement(other);
936 			} else enforceJson(false, "'~=' only allowed for string and array types, not "~m_type.enumToString~".");
937 		} else static assert(0, "Unsupported operator '"~op~"=' for type JSON.");
938 	}
939 	/// ditto
940 	void opOpAssign(string op, T)(T other)
941 		if (!is(T == Json) && is(typeof(Json(other))))
942 	{
943 		opOpAssign!op(Json(other));
944 	}
945 	/// ditto
946 	Json opBinary(string op)(bool other) const { checkType!bool(); mixin("return Json(m_bool "~op~" other);"); }
947 	/// ditto
948 	Json opBinary(string op)(long other) const @trusted
949 	{
950 		checkType!(long, BigInt)();
951 		if (m_type == Type.bigInt)
952 			mixin("return Json(m_bigInt "~op~" other);");
953 		else
954 			mixin("return Json(m_int "~op~" other);");
955 	}
956 	/// ditto
957 	Json opBinary(string op)(BigInt other) const @trusted
958 	{
959 		checkType!(long, BigInt)();
960 		if (m_type == Type.bigInt)
961 			mixin("return Json(m_bigInt "~op~" other);");
962 		else
963 			mixin("return Json(m_int "~op~" other);");
964 	}
965 	/// ditto
966 	Json opBinary(string op)(double other) const { checkType!double(); mixin("return Json(m_float "~op~" other);"); }
967 	/// ditto
968 	Json opBinary(string op)(string other) const @trusted { checkType!string(); mixin("return Json(m_string "~op~" other);"); }
969 	/// ditto
970 	Json opBinary(string op)(Json[] other) @trusted { checkType!(Json[])(); mixin("return Json(m_array "~op~" other);"); }
971 	/// ditto
972 	Json opBinaryRight(string op)(bool other) const { checkType!bool(); mixin("return Json(other "~op~" m_bool);"); }
973 	/// ditto
974 	Json opBinaryRight(string op)(long other) const @trusted
975 	{
976 		checkType!(long, BigInt)();
977 		if (m_type == Type.bigInt)
978 			mixin("return Json(other "~op~" m_bigInt);");
979 		else
980 			mixin("return Json(other "~op~" m_int);");
981 	}
982 	/// ditto
983 	Json opBinaryRight(string op)(BigInt other) const @trusted
984 	{
985 		checkType!(long, BigInt)();
986 		if (m_type == Type.bigInt)
987 			mixin("return Json(other "~op~" m_bigInt);");
988 		else
989 			mixin("return Json(other "~op~" m_int);");
990 	}
991 	/// ditto
992 	Json opBinaryRight(string op)(double other) const { checkType!double(); mixin("return Json(other "~op~" m_float);"); }
993 	/// ditto
994 	Json opBinaryRight(string op)(string other) const @trusted if(op == "~")
995 	{
996 		checkType!string();
997 		return Json(other ~ m_string);
998 	}
999 	/// ditto
1000 	Json opBinaryRight(string op)(Json[] other) @trusted { checkType!(Json[])(); mixin("return Json(other "~op~" m_array);"); }
1001 
1002 
1003 	/** Checks wheter a particular key is set and returns a pointer to it.
1004 
1005 		For field that don't exist or have a type of `Type.undefined`,
1006 		the `in` operator will return `null`.
1007 	*/
1008 	inout(Json)* opBinaryRight(string op)(string other) inout @trusted
1009 		if(op == "in")
1010 	{
1011 		checkType!(Json[string])();
1012 		auto pv = other in m_object;
1013 		if (!pv) return null;
1014 		if (pv.type == Type.undefined) return null;
1015 		return pv;
1016 	}
1017 
1018 	///
1019 	@safe unittest {
1020 		auto j = Json.emptyObject;
1021 		j["a"] = "foo";
1022 		j["b"] = Json.undefined;
1023 
1024 		assert("a" in j);
1025 		assert(("a" in j).get!string == "foo");
1026 		assert("b" !in j);
1027 		assert("c" !in j);
1028 	}
1029 
1030 
1031 	/**
1032 	 * The append operator will append arrays. This method always appends it's argument as an array element, so nested arrays can be created.
1033 	 */
1034 	void appendArrayElement(Json element)
1035 	@trusted {
1036 		enforceJson(m_type == Type.array, "'appendArrayElement' only allowed for array types, not "~m_type.enumToString~".");
1037 		m_array ~= element;
1038 	}
1039 
1040 	/**
1041 		Compares two JSON values for equality.
1042 
1043 		If the two values have different types, they are considered unequal.
1044 		This differs with ECMA script, which performs a type conversion before
1045 		comparing the values.
1046 	*/
1047 
1048 	bool opEquals(ref const Json other)
1049 	const @trusted {
1050 		if( m_type != other.m_type ) return false;
1051 		final switch(m_type){
1052 			case Type.undefined: return false;
1053 			case Type.null_: return true;
1054 			case Type.bool_: return m_bool == other.m_bool;
1055 			case Type.int_: return m_int == other.m_int;
1056 			case Type.bigInt: return m_bigInt == other.m_bigInt;
1057 			case Type.float_: return m_float == other.m_float;
1058 			case Type..string: return m_string == other.m_string;
1059 			case Type.array: return m_array == other.m_array;
1060 			case Type.object: return m_object == other.m_object;
1061 		}
1062 	}
1063 	/// ditto
1064 	bool opEquals(const Json other) const { return opEquals(other); }
1065 	/// ditto
1066 	bool opEquals(typeof(null)) const { return m_type == Type.null_; }
1067 	/// ditto
1068 	bool opEquals(bool v) const { return m_type == Type.bool_ && m_bool == v; }
1069 	/// ditto
1070 	bool opEquals(int v) const @trusted { return (m_type == Type.int_ && m_int == v) || (m_type == Type.bigInt && m_bigInt == v); }
1071 	/// ditto
1072 	bool opEquals(long v) const @trusted { return (m_type == Type.int_ && m_int == v) || (m_type == Type.bigInt && m_bigInt == v); }
1073 	/// ditto
1074 	bool opEquals(BigInt v) const @trusted { return (m_type == Type.int_ && m_int == v) || (m_type == Type.bigInt && m_bigInt == v); }
1075 	/// ditto
1076 	bool opEquals(double v) const { return m_type == Type.float_ && m_float == v; }
1077 	/// ditto
1078 	bool opEquals(string v) const @trusted { return m_type == Type..string && m_string == v; }
1079 
1080 	/**
1081 		Compares two JSON values.
1082 
1083 		If the types of the two values differ, the value with the smaller type
1084 		id is considered the smaller value. This differs from ECMA script, which
1085 		performs a type conversion before comparing the values.
1086 
1087 		JSON values of type Object cannot be compared and will throw an
1088 		exception.
1089 	*/
1090 	int opCmp(ref const Json other)
1091 	const @trusted {
1092 		if( m_type != other.m_type ) return m_type < other.m_type ? -1 : 1;
1093 		final switch(m_type){
1094 			case Type.undefined: return 0;
1095 			case Type.null_: return 0;
1096 			case Type.bool_: return m_bool < other.m_bool ? -1 : m_bool == other.m_bool ? 0 : 1;
1097 			case Type.int_: return m_int < other.m_int ? -1 : m_int == other.m_int ? 0 : 1;
1098 			case Type.bigInt: return () @trusted { return m_bigInt < other.m_bigInt; } () ? -1 : m_bigInt == other.m_bigInt ? 0 : 1;
1099 			case Type.float_: return m_float < other.m_float ? -1 : m_float == other.m_float ? 0 : 1;
1100 			case Type..string: return m_string < other.m_string ? -1 : m_string == other.m_string ? 0 : 1;
1101 			case Type.array: return m_array < other.m_array ? -1 : m_array == other.m_array ? 0 : 1;
1102 			case Type.object:
1103 				enforceJson(false, "JSON objects cannot be compared.");
1104 				assert(false);
1105 		}
1106 	}
1107 
1108 	alias opDollar = length;
1109 
1110 	/**
1111 		Returns the type id corresponding to the given D type.
1112 	*/
1113 	static @property Type typeId(T)() {
1114 		static if( is(T == typeof(null)) ) return Type.null_;
1115 		else static if( is(T == bool) ) return Type.bool_;
1116 		else static if( is(T == double) ) return Type.float_;
1117 		else static if( is(T == float) ) return Type.float_;
1118 		else static if( is(T : long) ) return Type.int_;
1119 		else static if( is(T == string) ) return Type..string;
1120 		else static if( is(T == UUID) ) return Type..string;
1121 		else static if( is(T == Json[]) ) return Type.array;
1122 		else static if( is(T == Json[string]) ) return Type.object;
1123 		else static if( is(T == BigInt) ) return Type.bigInt;
1124 		else static assert(false, "Unsupported JSON type '"~T.stringof~"'. Only bool, long, std.bigint.BigInt, double, string, Json[] and Json[string] are allowed.");
1125 	}
1126 
1127 	/**
1128 		Returns the JSON object as a string.
1129 
1130 		For large JSON values use writeJsonString instead as this function will store the whole string
1131 		in memory, whereas writeJsonString writes it out bit for bit.
1132 
1133 		See_Also: writeJsonString, toPrettyString
1134 	*/
1135 	string toString()
1136 	const @trusted {
1137 		// DMD BUG: this should actually be all @safe, but for some reason
1138 		// @safe inference for writeJsonString doesn't work.
1139 		auto ret = appender!string();
1140 		writeJsonString(ret, this);
1141 		return ret.data;
1142 	}
1143 	/// ditto
1144 	void toString(scope void delegate(const(char)[]) @safe sink, FormatSpec!char fmt)
1145 	@trusted {
1146 		// DMD BUG: this should actually be all @safe, but for some reason
1147 		// @safe inference for writeJsonString doesn't work.
1148 		static struct DummyRangeS {
1149 			void delegate(const(char)[]) @safe sink;
1150 			void put(const(char)[] str) @safe { sink(str); }
1151 			void put(char ch) @trusted { sink((&ch)[0 .. 1]); }
1152 		}
1153 		auto r = DummyRangeS(sink);
1154 		writeJsonString(r, this);
1155 	}
1156 	/// ditto
1157 	void toString(scope void delegate(const(char)[]) @system sink, FormatSpec!char fmt)
1158 	@system {
1159 		// DMD BUG: this should actually be all @safe, but for some reason
1160 		// @safe inference for writeJsonString doesn't work.
1161 		static struct DummyRange {
1162 			void delegate(const(char)[]) sink;
1163 			@trusted:
1164 			void put(const(char)[] str) { sink(str); }
1165 			void put(char ch) { sink((&ch)[0 .. 1]); }
1166 		}
1167 		auto r = DummyRange(sink);
1168 		writeJsonString(r, this);
1169 	}
1170 
1171 	/**
1172 		Returns the JSON object as a "pretty" string.
1173 
1174 		---
1175 		auto json = Json(["foo": Json("bar")]);
1176 		writeln(json.toPrettyString());
1177 
1178 		// output:
1179 		// {
1180 		//     "foo": "bar"
1181 		// }
1182 		---
1183 
1184 		Params:
1185 			level = Specifies the base amount of indentation for the output. Indentation  is always
1186 				done using tab characters.
1187 
1188 		See_Also: writePrettyJsonString, toString
1189 	*/
1190 	string toPrettyString(int level = 0)
1191 	const @trusted {
1192 		auto ret = appender!string();
1193 		writePrettyJsonString(ret, this, level);
1194 		return ret.data;
1195 	}
1196 
1197 	private void checkType(TYPES...)(string op = null)
1198 	const {
1199 		bool matched = false;
1200 		foreach (T; TYPES) if (m_type == typeId!T) matched = true;
1201 		if (matched) return;
1202 
1203 		string name;
1204 		version (VibeJsonFieldNames) {
1205 			if (m_name.length) name = m_name ~ " of type " ~ m_type.enumToString;
1206 			else name = "JSON of type " ~ m_type.enumToString;
1207 		} else name = "JSON of type " ~ m_type.enumToString;
1208 
1209 		string expected;
1210 		static if (TYPES.length == 1) expected = typeId!(TYPES[0]).enumToString;
1211 		else {
1212 			foreach (T; TYPES) {
1213 				if (expected.length > 0) expected ~= ", ";
1214 				expected ~= typeId!T.enumToString;
1215 			}
1216 		}
1217 
1218 		if (!op.length) throw new JSONException(format("Got %s, expected %s.", name, expected));
1219 		else throw new JSONException(format("Got %s, expected %s for %s.", name, expected, op));
1220 	}
1221 
1222 	private void initBigInt()
1223 	nothrow @trusted {
1224 		// BigInt is a struct, and it has a special BigInt.init value, which differs from null.
1225 		m_bigInt = BigInt.init;
1226 	}
1227 
1228 	private void runDestructors()
1229 	nothrow @trusted {
1230 		if (m_type != Type.bigInt)
1231 		{
1232 			zeroFields;
1233 			return;
1234 		}
1235 
1236 		BigInt init_;
1237 		// After swaping, init_ contains the real number from Json, and it
1238 		// will be destroyed when this function is finished.
1239 		// m_bigInt now contains static BigInt.init value and destruction may
1240 		// be ommited for it.
1241 		swap(init_, m_bigInt);
1242 	}
1243 
1244 	private long bigIntToLong() inout @trusted
1245 	{
1246 		assert(m_type == Type.bigInt, format("Converting non-bigInt type with bitIntToLong!?: %s", (cast(Type)m_type).enumToString));
1247 		enforceJson(m_bigInt >= long.min && m_bigInt <= long.max, "Number out of range while converting BigInt("~format("%d", m_bigInt)~") to long.");
1248 		return m_bigInt.toLong();
1249 	}
1250 
1251 	/*invariant()
1252 	{
1253 		assert(m_type >= Type.Undefined && m_type <= Type.Object);
1254 	}*/
1255 }
1256 
1257 @safe unittest { // issue #1234 - @safe toString
1258 	auto j = Json(true);
1259 	j.toString((str) @safe {}, FormatSpec!char("s"));
1260 	assert(j.toString() == "true");
1261 }
1262 
1263 
1264 /******************************************************************************/
1265 /* public functions                                                           */
1266 /******************************************************************************/
1267 
1268 /**
1269 	Parses the given range as a JSON string and returns the corresponding Json object.
1270 
1271 	The range is shrunk during parsing, leaving any remaining text that is not part of
1272 	the JSON contents.
1273 
1274 	Throws a JSONException if any parsing error occured.
1275 */
1276 Json parseJson(R)(ref R range, int* line = null, string filename = null)
1277 	if (isForwardRange!R)
1278 {
1279 	Json ret;
1280 	enforceJson(!range.empty, "JSON string is empty.", filename, 0);
1281 
1282 	skipWhitespace(range, line);
1283 
1284 	enforceJson(!range.empty, "JSON string contains only whitespaces.", filename, 0);
1285 
1286 	version(JsonLineNumbers) {
1287 		int curline = line ? *line : 0;
1288 	}
1289 
1290 	bool minus = false;
1291 	switch( range.front ){
1292 		case 'f':
1293 			enforceJson(range.save.dropOne.startsWith("alse"),
1294 				"Expected 'false', got '"~range.take(5).to!string~"'.", filename, line);
1295 			range.popFrontN(5);
1296 			ret = false;
1297 			break;
1298 		case 'n':
1299 			enforceJson(range.save.dropOne.startsWith("ull"),
1300 				"Expected 'null', got '"~range.take(4).to!string~"'.", filename, line);
1301 			range.popFrontN(4);
1302 			ret = null;
1303 			break;
1304 		case 't':
1305 			enforceJson(range.save.dropOne.startsWith("rue"),
1306 				"Expected 'true', got '"~range.take(4).to!string~"'.", filename, line);
1307 			range.popFrontN(4);
1308 			ret = true;
1309 			break;
1310 
1311 		case '-':
1312 		case '0': .. case '9':
1313 			bool is_long_overflow;
1314 			bool is_float;
1315 			auto num = skipNumber(range, is_float, is_long_overflow);
1316 			if( is_float ) {
1317 				ret = to!double(num);
1318 			} else if (is_long_overflow) {
1319 				ret = () @trusted { return BigInt(num.to!string); } ();
1320 			} else {
1321 				ret = to!long(num);
1322 			}
1323 			break;
1324 		case '\"':
1325 			ret = skipJsonString(range);
1326 			break;
1327 		case '[':
1328 			auto arr = appender!(Json[]);
1329 			range.popFront();
1330 			while (true) {
1331 				skipWhitespace(range, line);
1332 				enforceJson(!range.empty, "Missing ']' before EOF.", filename, line);
1333 				if(range.front == ']') break;
1334 				arr ~= parseJson(range, line, filename);
1335 				skipWhitespace(range, line);
1336 				enforceJson(!range.empty, "Missing ']' before EOF.", filename, line);
1337 				enforceJson(range.front == ',' || range.front == ']',
1338 					format("Expected ']' or ',' - got '%s'.", range.front), filename, line);
1339 				if( range.front == ']' ) break;
1340 				else range.popFront();
1341 			}
1342 			range.popFront();
1343 			ret = arr.data;
1344 			break;
1345 		case '{':
1346 			Json[string] obj;
1347 			range.popFront();
1348 			while (true) {
1349 				skipWhitespace(range, line);
1350 				enforceJson(!range.empty, "Missing '}' before EOF.", filename, line);
1351 				if(range.front == '}') break;
1352 				string key = skipJsonString(range);
1353 				skipWhitespace(range, line);
1354 				enforceJson(range.startsWith(":"), "Expected ':' for key '" ~ key ~ "'", filename, line);
1355 				range.popFront();
1356 				skipWhitespace(range, line);
1357 				Json itm = parseJson(range, line, filename);
1358 				obj[key] = itm;
1359 				skipWhitespace(range, line);
1360 				enforceJson(!range.empty, "Missing '}' before EOF.", filename, line);
1361 				enforceJson(range.front == ',' || range.front == '}',
1362 					format("Expected '}' or ',' - got '%s'.", range.front), filename, line);
1363 				if (range.front == '}') break;
1364 				else range.popFront();
1365 			}
1366 			range.popFront();
1367 			ret = obj;
1368 			break;
1369 		default:
1370 			enforceJson(false, format("Expected valid JSON token, got '%s'.", range.take(12)), filename, line);
1371 			assert(false);
1372 	}
1373 
1374 	assert(ret.type != Json.Type.undefined);
1375 	version(JsonLineNumbers) ret.line = curline;
1376 	return ret;
1377 }
1378 
1379 
1380 unittest { // ensure parseJson works with a generic forward range
1381 	static struct R {
1382 		const(char)[] text;
1383 
1384 		@property char front() { return text[0]; }
1385 		@property R save() { return this; }
1386 		@property bool empty() const { return text.length == 0; }
1387 		void popFront() { text = text[1 .. $]; }
1388 	}
1389 
1390 	auto r = R(`{"i":42, "s": "foo"}`);
1391 	auto j = parseJson(r);
1392 	assert(j["i"] == 42);
1393 	assert(j["s"] == "foo");
1394 }
1395 
1396 
1397 /**
1398 	Parses the given JSON string and returns the corresponding Json object.
1399 
1400 	Throws a JSONException if any parsing error occurs.
1401 */
1402 Json parseJsonString(string str, string filename = null)
1403 @safe {
1404 	auto strcopy = str;
1405 	int line = 0;
1406 	auto ret = parseJson(strcopy, () @trusted { return &line; } (), filename);
1407 	enforceJson(strcopy.strip().length == 0, "Expected end of string after JSON value.", filename, line);
1408 	return ret;
1409 }
1410 
1411 @safe unittest {
1412 	// These currently don't work at compile time
1413 	assert(parseJsonString("17559991181826658461") == Json(BigInt(17559991181826658461UL)));
1414 	assert(parseJsonString("99999999999999999999999999") == () @trusted { return Json(BigInt("99999999999999999999999999")); } ());
1415 	auto json = parseJsonString(`{"hey": "This is @à test éhééhhéhéé !%/??*&?\ud83d\udcec"}`);
1416 	assert(json.toPrettyString() == parseJsonString(json.toPrettyString()).toPrettyString());
1417 
1418 	bool test() {
1419 		assert(parseJsonString("null") == Json(null));
1420 		assert(parseJsonString("true") == Json(true));
1421 		assert(parseJsonString("false") == Json(false));
1422 		assert(parseJsonString("1") == Json(1));
1423 		assert(parseJsonString("2.0") == Json(2.0));
1424 		assert(parseJsonString("\"test\"") == Json("test"));
1425 		assert(parseJsonString("[1, 2, 3]") == Json([Json(1), Json(2), Json(3)]));
1426 		assert(parseJsonString("{\"a\": 1}") == Json(["a": Json(1)]));
1427 		assert(parseJsonString(`"\\\/\b\f\n\r\t\u1234"`).get!string == "\\/\b\f\n\r\t\u1234");
1428 
1429 		return true;
1430 	}
1431 
1432 	// Run at compile time and runtime
1433 	assert(test());
1434 	static assert(test());
1435 }
1436 
1437 @safe nothrow unittest {
1438 	bool test() {
1439 		try parseJsonString(" \t\n ");
1440 		catch (Exception e) assert(e.msg.endsWith("JSON string contains only whitespaces."));
1441 		try parseJsonString(`{"a": 1`);
1442 		catch (Exception e) assert(e.msg.endsWith("Missing '}' before EOF."));
1443 		try parseJsonString(`{"a": 1 x`);
1444 		catch (Exception e) assert(e.msg.endsWith("Expected '}' or ',' - got 'x'."));
1445 		try parseJsonString(`[1`);
1446 		catch (Exception e) assert(e.msg.endsWith("Missing ']' before EOF."));
1447 		try parseJsonString(`[1 x`);
1448 		catch (Exception e) assert(e.msg.endsWith("Expected ']' or ',' - got 'x'."));
1449 
1450 		return true;
1451 	}
1452 
1453 	// Run at compile time and runtime
1454 	assert(test());
1455 	static assert(test());
1456 }
1457 
1458 /**
1459 	Serializes the given value to JSON.
1460 
1461 	The following types of values are supported:
1462 
1463 	$(DL
1464 		$(DT `Json`)            $(DD Used as-is)
1465 		$(DT `null`)            $(DD Converted to `Json.Type.null_`)
1466 		$(DT `bool`)            $(DD Converted to `Json.Type.bool_`)
1467 		$(DT `float`, `double`)   $(DD Converted to `Json.Type.float_`)
1468 		$(DT `short`, `ushort`, `int`, `uint`, `long`, `ulong`) $(DD Converted to `Json.Type.int_`)
1469 		$(DT `BigInt`)          $(DD Converted to `Json.Type.bigInt`)
1470 		$(DT `string`)          $(DD Converted to `Json.Type.string`)
1471 		$(DT `T[]`)             $(DD Converted to `Json.Type.array`)
1472 		$(DT `T[string]`)       $(DD Converted to `Json.Type.object`)
1473 		$(DT `struct`)          $(DD Converted to `Json.Type.object`)
1474 		$(DT `class`)           $(DD Converted to `Json.Type.object` or `Json.Type.null_`)
1475 	)
1476 
1477 	All entries of an array or an associative array, as well as all R/W properties and
1478 	all public fields of a struct/class are recursively serialized using the same rules.
1479 
1480 	Fields ending with an underscore will have the last underscore stripped in the
1481 	serialized output. This makes it possible to use fields with D keywords as their name
1482 	by simply appending an underscore.
1483 
1484 	The following methods can be used to customize the serialization of structs/classes:
1485 
1486 	---
1487 	Json toJson() const;
1488 	static T fromJson(Json src);
1489 
1490 	string toString() const;
1491 	static T fromString(string src);
1492 	---
1493 
1494 	The methods will have to be defined in pairs. The first pair that is implemented by
1495 	the type will be used for serialization (i.e. `toJson` overrides `toString`).
1496 
1497 	See_Also: `deserializeJson`, `vibe.data.serialization`
1498 */
1499 Json serializeToJson(T)(auto ref T value)
1500 {
1501 	return serialize!JsonSerializer(value);
1502 }
1503 /// ditto
1504 void serializeToJson(R, T)(R destination, auto ref T value)
1505 	if (isOutputRange!(R, char) || isOutputRange!(R, ubyte))
1506 {
1507 	serialize!(JsonStringSerializer!R)(value, destination);
1508 }
1509 /// ditto
1510 string serializeToJsonString(T)(auto ref T value)
1511 {
1512 	auto ret = appender!string;
1513 	serializeToJson(ret, value);
1514 	return ret.data;
1515 }
1516 
1517 ///
1518 @safe unittest {
1519 	struct Foo {
1520 		int number;
1521 		string str;
1522 	}
1523 
1524 	Foo f;
1525 
1526 	f.number = 12;
1527 	f.str = "hello";
1528 
1529 	string json = serializeToJsonString(f);
1530 	assert(json == `{"number":12,"str":"hello"}`);
1531 	Json jsonval = serializeToJson(f);
1532 	assert(jsonval.type == Json.Type.object);
1533 	assert(jsonval["number"] == Json(12));
1534 	assert(jsonval["str"] == Json("hello"));
1535 }
1536 
1537 
1538 /**
1539 	Serializes the given value to a pretty printed JSON string.
1540 
1541 	See_also: `serializeToJson`, `vibe.data.serialization`
1542 */
1543 void serializeToPrettyJson(R, T)(R destination, auto ref T value)
1544 	if (isOutputRange!(R, char) || isOutputRange!(R, ubyte))
1545 {
1546 	serialize!(JsonStringSerializer!(R, true))(value, destination);
1547 }
1548 /// ditto
1549 string serializeToPrettyJson(T)(auto ref T value)
1550 {
1551 	auto ret = appender!string;
1552 	serializeToPrettyJson(ret, value);
1553 	return ret.data;
1554 }
1555 
1556 ///
1557 @safe unittest {
1558 	struct Foo {
1559 		int number;
1560 		string str;
1561 	}
1562 
1563 	Foo f;
1564 	f.number = 12;
1565 	f.str = "hello";
1566 
1567 	string json = serializeToPrettyJson(f);
1568 	assert(json ==
1569 `{
1570 	"number": 12,
1571 	"str": "hello"
1572 }`);
1573 }
1574 
1575 
1576 /**
1577 	Deserializes a JSON value into the destination variable.
1578 
1579 	The same types as for `serializeToJson()` are supported and handled inversely.
1580 
1581 	See_Also: `serializeToJson`, `serializeToJsonString`, `vibe.data.serialization`
1582 */
1583 void deserializeJson(T)(ref T dst, Json src)
1584 {
1585 	dst = deserializeJson!T(src);
1586 }
1587 /// ditto
1588 T deserializeJson(T)(Json src)
1589 {
1590 	return deserialize!(JsonSerializer, T)(src);
1591 }
1592 /// ditto
1593 T deserializeJson(T, R)(R input)
1594 	if (!is(R == Json) && isForwardRange!R)
1595 {
1596 	return deserialize!(JsonStringSerializer!R, T)(input);
1597 }
1598 
1599 ///
1600 @safe unittest {
1601 	struct Foo {
1602 		int number;
1603 		string str;
1604 	}
1605 	Foo f = deserializeJson!Foo(`{"number": 12, "str": "hello"}`);
1606 	assert(f.number == 12);
1607 	assert(f.str == "hello");
1608 }
1609 
1610 @safe unittest {
1611 	import std.stdio;
1612 	enum Foo : string { k = "test" }
1613 	enum Boo : int { l = 5 }
1614 	static struct S { float a; double b; bool c; int d; string e; byte f; ubyte g; long h; ulong i; float[] j; Foo k; Boo l; }
1615 	immutable S t = {1.5, -3.0, true, int.min, "Test", -128, 255, long.min, ulong.max, [1.1, 1.2, 1.3], Foo.k, Boo.l};
1616 	S u;
1617 	deserializeJson(u, serializeToJson(t));
1618 	assert(t.a == u.a);
1619 	assert(t.b == u.b);
1620 	assert(t.c == u.c);
1621 	assert(t.d == u.d);
1622 	assert(t.e == u.e);
1623 	assert(t.f == u.f);
1624 	assert(t.g == u.g);
1625 	assert(t.h == u.h);
1626 	assert(t.i == u.i);
1627 	assert(t.j == u.j);
1628 	assert(t.k == u.k);
1629 	assert(t.l == u.l);
1630 }
1631 
1632 @safe unittest
1633 {
1634 	assert(uint.max == serializeToJson(uint.max).deserializeJson!uint);
1635 	assert(ulong.max == serializeToJson(ulong.max).deserializeJson!ulong);
1636 }
1637 
1638 @safe unittest {
1639 	static struct A { int value; static A fromJson(Json val) @safe { return A(val.get!int); } Json toJson() const @safe { return Json(value); } }
1640 	static struct C { int value; static C fromString(string val) @safe { return C(val.to!int); } string toString() const @safe { return value.to!string; } }
1641 	static struct D { int value; }
1642 
1643 	assert(serializeToJson(const A(123)) == Json(123));
1644 	assert(serializeToJson(A(123))       == Json(123));
1645 	assert(serializeToJson(const C(123)) == Json("123"));
1646 	assert(serializeToJson(C(123))       == Json("123"));
1647 	assert(serializeToJson(const D(123)) == serializeToJson(["value": 123]));
1648 	assert(serializeToJson(D(123))       == serializeToJson(["value": 123]));
1649 }
1650 
1651 @safe unittest {
1652 	auto d = Date(2001,1,1);
1653 	deserializeJson(d, serializeToJson(Date.init));
1654 	assert(d == Date.init);
1655 	deserializeJson(d, serializeToJson(Date(2001,1,1)));
1656 	assert(d == Date(2001,1,1));
1657 	struct S { immutable(int)[] x; }
1658 	S s;
1659 	deserializeJson(s, serializeToJson(S([1,2,3])));
1660 	assert(s == S([1,2,3]));
1661 	struct T {
1662 		@optional S s;
1663 		@optional int i;
1664 		@optional float f_; // underscore strip feature
1665 		@optional double d;
1666 		@optional string str;
1667 	}
1668 	auto t = T(S([1,2,3]));
1669 	deserializeJson(t, parseJsonString(`{ "s" : null, "i" : null, "f" : null, "d" : null, "str" : null }`));
1670 	assert(text(t) == text(T()));
1671 }
1672 
1673 @safe unittest {
1674 	static class C {
1675 		@safe:
1676 		int a;
1677 		private int _b;
1678 		@property int b() const { return _b; }
1679 		@property void b(int v) { _b = v; }
1680 
1681 		@property int test() const { return 10; }
1682 
1683 		void test2() {}
1684 	}
1685 	C c = new C;
1686 	c.a = 1;
1687 	c.b = 2;
1688 
1689 	C d;
1690 	deserializeJson(d, serializeToJson(c));
1691 	assert(c.a == d.a);
1692 	assert(c.b == d.b);
1693 }
1694 
1695 @safe unittest {
1696 	static struct C { @safe: int value; static C fromString(string val) { return C(val.to!int); } string toString() const { return value.to!string; } }
1697 	enum Color { Red, Green, Blue }
1698 	{
1699 		static class T {
1700 			@safe:
1701 			string[Color] enumIndexedMap;
1702 			string[C] stringableIndexedMap;
1703 			this() {
1704 				enumIndexedMap = [ Color.Red : "magenta", Color.Blue : "deep blue" ];
1705 								stringableIndexedMap = [ C(42) : "forty-two" ];
1706 			}
1707 		}
1708 
1709 		T original = new T;
1710 		original.enumIndexedMap[Color.Green] = "olive";
1711 		T other;
1712 		deserializeJson(other, serializeToJson(original));
1713 		assert(serializeToJson(other) == serializeToJson(original));
1714 	}
1715 	{
1716 		static struct S {
1717 			string[Color] enumIndexedMap;
1718 			string[C] stringableIndexedMap;
1719 		}
1720 
1721 		S *original = new S;
1722 		original.enumIndexedMap = [ Color.Red : "magenta", Color.Blue : "deep blue" ];
1723 		original.enumIndexedMap[Color.Green] = "olive";
1724 				original.stringableIndexedMap = [ C(42) : "forty-two" ];
1725 		S other;
1726 		deserializeJson(other, serializeToJson(original));
1727 		assert(serializeToJson(other) == serializeToJson(original));
1728 	}
1729 }
1730 
1731 @safe unittest {
1732 	import std.typecons : Nullable;
1733 
1734 	struct S { Nullable!int a, b; }
1735 	S s;
1736 	s.a = 2;
1737 
1738 	auto j = serializeToJson(s);
1739 	assert(j["a"].type == Json.Type.int_);
1740 	assert(j["b"].type == Json.Type.null_);
1741 
1742 	auto t = deserializeJson!S(j);
1743 	assert(!t.a.isNull() && t.a == 2);
1744 	assert(t.b.isNull());
1745 }
1746 
1747 @safe unittest { // #840
1748 	int[2][2] nestedArray = 1;
1749 	assert(nestedArray.serializeToJson.deserializeJson!(typeof(nestedArray)) == nestedArray);
1750 }
1751 
1752 @safe unittest { // #1109
1753 	static class C {
1754 		@safe:
1755 		int mem;
1756 		this(int m) { mem = m; }
1757 		static C fromJson(Json j) { return new C(j.get!int-1); }
1758 		Json toJson() const { return Json(mem+1); }
1759 	}
1760 	const c = new C(13);
1761 	assert(serializeToJson(c) == Json(14));
1762 	assert(deserializeJson!C(Json(14)).mem == 13);
1763 }
1764 
1765 @safe unittest { // const and mutable json
1766 	Json j = Json(1);
1767 	const k = Json(2);
1768 	assert(serializeToJson(j) == Json(1));
1769 	assert(serializeToJson(k) == Json(2));
1770 }
1771 
1772 @safe unittest { // issue #1660 - deserialize AA whose key type is string-based enum
1773 	enum Foo: string
1774 	{
1775 		Bar = "bar",
1776 		Buzz = "buzz"
1777 	}
1778 
1779 	struct S {
1780 		int[Foo] f;
1781 	}
1782 
1783 	const s = S([Foo.Bar: 2000]);
1784 	assert(serializeToJson(s)["f"] == Json([Foo.Bar: Json(2000)]));
1785 
1786 	auto j = Json.emptyObject;
1787 	j["f"] = [Foo.Bar: Json(2000)];
1788 	assert(deserializeJson!S(j).f == [Foo.Bar: 2000]);
1789 }
1790 
1791 @safe unittest {
1792 	struct V {
1793 		UUID v;
1794 	}
1795 
1796 	const u = UUID("318d7a61-e41b-494e-90d3-0a99f5531bfe");
1797 	const s = `{"v":"318d7a61-e41b-494e-90d3-0a99f5531bfe"}`;
1798 	auto j = Json(["v": Json(u)]);
1799 
1800 	const v = V(u);
1801 
1802 	assert(serializeToJson(v) == j);
1803 
1804 	j = Json.emptyObject;
1805 	j["v"] = u;
1806 	assert(deserializeJson!V(j).v == u);
1807 
1808 	assert(serializeToJsonString(v) == s);
1809 	assert(deserializeJson!V(s).v == u);
1810 }
1811 
1812 /**
1813 	Serializer for a plain Json representation.
1814 
1815 	See_Also: vibe.data.serialization.serialize, vibe.data.serialization.deserialize, serializeToJson, deserializeJson
1816 */
1817 struct JsonSerializer {
1818 	template isJsonBasicType(T) { enum isJsonBasicType = std.traits.isNumeric!T || isBoolean!T || isSomeString!T || is(T == typeof(null)) || is(Unqual!T == UUID) || isJsonSerializable!T; }
1819 
1820 	template isSupportedValueType(T) { enum isSupportedValueType = isJsonBasicType!T || is(Unqual!T == Json) || is(Unqual!T == JSONValue); }
1821 
1822 	private {
1823 		Json m_current;
1824 		Json[] m_compositeStack;
1825 	}
1826 
1827 	this(Json data) @safe { m_current = data; }
1828 
1829 	@disable this(this);
1830 
1831 	//
1832 	// serialization
1833 	//
1834 	Json getSerializedResult() @safe { return m_current; }
1835 	void beginWriteDictionary(Traits)() { m_compositeStack ~= Json.emptyObject; }
1836 	void endWriteDictionary(Traits)() { m_current = m_compositeStack[$-1]; m_compositeStack.length--; }
1837 	void beginWriteDictionaryEntry(Traits)(string name) {}
1838 	void endWriteDictionaryEntry(Traits)(string name) { m_compositeStack[$-1][name] = m_current; }
1839 
1840 	void beginWriteArray(Traits)(size_t) { m_compositeStack ~= Json.emptyArray; }
1841 	void endWriteArray(Traits)() { m_current = m_compositeStack[$-1]; m_compositeStack.length--; }
1842 	void beginWriteArrayEntry(Traits)(size_t) {}
1843 	void endWriteArrayEntry(Traits)(size_t) { m_compositeStack[$-1].appendArrayElement(m_current); }
1844 
1845 	void writeValue(Traits, T)(auto ref T value)
1846 		if (!is(Unqual!T == Json))
1847 	{
1848 		alias UT = Unqual!T;
1849 		static if (is(UT == JSONValue)) {
1850 			m_current = Json(value);
1851 		} else static if (isJsonSerializable!UT) {
1852 			static if (!__traits(compiles, () @safe { return value.toJson(); } ()))
1853 				pragma(msg, "Non-@safe toJson/fromJson methods are deprecated - annotate "~UT.stringof~".toJson() with @safe.");
1854 			m_current = () @trusted { return value.toJson(); } ();
1855 		} else static if (isSomeString!T && !is(UT == string)) {
1856 			writeValue!Traits(value.to!string);
1857 		} else m_current = Json(value);
1858 	}
1859 
1860 	void writeValue(Traits, T)(auto ref T value) if (is(T == Json)) { m_current = value; }
1861 	void writeValue(Traits, T)(auto ref T value) if (!is(T == Json) && is(T : const(Json))) { m_current = value.clone; }
1862 
1863 	//
1864 	// deserialization
1865 	//
1866 	void readDictionary(Traits)(scope void delegate(string) @safe field_handler)
1867 	{
1868 		enforceJson(m_current.type == Json.Type.object, "Expected JSON object, got "~m_current.type.enumToString);
1869 		auto old = m_current;
1870 		foreach (string key, value; m_current.get!(Json[string])) {
1871 			if (value.type == Json.Type.undefined) {
1872 				continue;
1873 			}
1874 
1875 			m_current = value;
1876 			field_handler(key);
1877 		}
1878 		m_current = old;
1879 	}
1880 
1881 	void beginReadDictionaryEntry(Traits)(string name) {}
1882 	void endReadDictionaryEntry(Traits)(string name) {}
1883 
1884 	void readArray(Traits)(scope void delegate(size_t) @safe size_callback, scope void delegate() @safe entry_callback)
1885 	{
1886 		enforceJson(m_current.type == Json.Type.array, "Expected JSON array, got "~m_current.type.enumToString);
1887 		auto old = m_current;
1888 		size_callback(m_current.length);
1889 		foreach (ent; old.get!(Json[])) {
1890 			m_current = ent;
1891 			entry_callback();
1892 		}
1893 		m_current = old;
1894 	}
1895 
1896 	void beginReadArrayEntry(Traits)(size_t index) {}
1897 	void endReadArrayEntry(Traits)(size_t index) {}
1898 
1899 	T readValue(Traits, T)()
1900 	@safe {
1901 		static if (is(T == Json)) return m_current;
1902 		else static if (is(T == JSONValue)) return cast(JSONValue)m_current;
1903 		else static if (isJsonSerializable!T) {
1904 			static if (!__traits(compiles, () @safe { return T.fromJson(m_current); } ()))
1905 				pragma(msg, "Non-@safe toJson/fromJson methods are deprecated - annotate "~T.stringof~".fromJson() with @safe.");
1906 			return () @trusted { return T.fromJson(m_current); } ();
1907 		} else static if (is(T == float) || is(T == double)) {
1908 			switch (m_current.type) {
1909 				default: return cast(T)m_current.get!long;
1910 				case Json.Type.null_: goto case;
1911 				case Json.Type.undefined: return T.nan;
1912 				case Json.Type.float_: return cast(T)m_current.get!double;
1913 				case Json.Type.bigInt: return cast(T)m_current.bigIntToLong();
1914 			}
1915 		} else static if (is(T == const(char)[])) {
1916 			return readValue!(Traits, string);
1917 		} else static if (isSomeString!T && !is(T == string)) {
1918 			return readValue!(Traits, string).to!T;
1919 		} else static if (is(T == string)) {
1920 			if (m_current.type == Json.Type.array) { // legacy support for pre-#2150 serialization results
1921 				return () @trusted { // appender
1922 					auto r = appender!string;
1923 					foreach (s; m_current.get!(Json[]))
1924 						r.put(s.get!string());
1925 					return r.data;
1926 				} ();
1927 			} else return m_current.get!T();
1928 		} else return m_current.get!T();
1929 	}
1930 
1931 	bool tryReadNull(Traits)() { return m_current.type == Json.Type.null_; }
1932 }
1933 
1934 unittest {
1935 	struct T {
1936 		@optional string a;
1937 	}
1938 
1939 	auto obj = Json.emptyObject;
1940 	obj["a"] = Json.undefined;
1941 	assert(obj.deserializeJson!T.a == "");
1942 }
1943 
1944 unittest {
1945 	class C { this(Json j) {foo = j;} Json foo; }
1946 	const C c = new C(Json(42));
1947 	assert(serializeToJson(c)["foo"].get!int == 42);
1948 }
1949 
1950 /**
1951 	Serializer for a range based plain JSON string representation.
1952 
1953 	See_Also: vibe.data.serialization.serialize, vibe.data.serialization.deserialize, serializeToJson, deserializeJson
1954 */
1955 struct JsonStringSerializer(R, bool pretty = false)
1956 	if (isInputRange!R || isOutputRange!(R, char))
1957 {
1958 	private {
1959 		R m_range;
1960 		size_t m_level = 0;
1961 	}
1962 
1963 	template isJsonBasicType(T) { enum isJsonBasicType = std.traits.isNumeric!T || isBoolean!T || isSomeString!T || is(T == typeof(null)) || is(Unqual!T == UUID) || isJsonSerializable!T; }
1964 
1965 	template isSupportedValueType(T) { enum isSupportedValueType = isJsonBasicType!(Unqual!T) || is(Unqual!T == Json) || is(Unqual!T == JSONValue); }
1966 
1967 	this(R range)
1968 	{
1969 		m_range = range;
1970 	}
1971 
1972 	@disable this(this);
1973 
1974 	//
1975 	// serialization
1976 	//
1977 	static if (isOutputRange!(R, char)) {
1978 		private {
1979 			bool m_firstInComposite;
1980 		}
1981 
1982 		void getSerializedResult() {}
1983 
1984 		void beginWriteDictionary(Traits)() { startComposite(); m_range.put('{'); }
1985 		void endWriteDictionary(Traits)() { endComposite(); m_range.put("}"); }
1986 		void beginWriteDictionaryEntry(Traits)(string name)
1987 		{
1988 			startCompositeEntry();
1989 			m_range.put('"');
1990 			m_range.jsonEscape(name);
1991 			static if (pretty) m_range.put(`": `);
1992 			else m_range.put(`":`);
1993 		}
1994 		void endWriteDictionaryEntry(Traits)(string name) {}
1995 
1996 		void beginWriteArray(Traits)(size_t) { startComposite(); m_range.put('['); }
1997 		void endWriteArray(Traits)() { endComposite(); m_range.put(']'); }
1998 		void beginWriteArrayEntry(Traits)(size_t) { startCompositeEntry(); }
1999 		void endWriteArrayEntry(Traits)(size_t) {}
2000 
2001 		void writeValue(Traits, T)(in T value)
2002 		{
2003 			alias UT = Unqual!T;
2004 			static if (is(T == typeof(null))) m_range.put("null");
2005 			else static if (is(UT == bool)) m_range.put(value ? "true" : "false");
2006 			else static if (is(UT : long)) m_range.formattedWrite("%s", value);
2007 			else static if (is(UT == BigInt)) () @trusted { m_range.formattedWrite("%d", value); } ();
2008 			else static if (is(UT : real)) value == value ? m_range.formattedWrite("%.16g", value) : m_range.put("null");
2009 			else static if (is(UT : const(char)[])) {
2010 				m_range.put('"');
2011 				m_range.jsonEscape(value);
2012 				m_range.put('"');
2013 			} else static if (isSomeString!T) writeValue!Traits(value.to!string); // TODO: avoid memory allocation
2014 			else static if (is(UT == UUID)) writeValue!Traits(value.toString());
2015 			else static if (is(UT == Json)) m_range.writeJsonString(value);
2016 			else static if (is(UT == JSONValue)) m_range.writeJsonString(Json(value));
2017 			else static if (isJsonSerializable!UT) {
2018 				static if (!__traits(compiles, () @safe { return value.toJson(); } ()))
2019 					pragma(msg, "Non-@safe toJson/fromJson methods are deprecated - annotate "~UT.stringof~".toJson() with @safe.");
2020 				m_range.writeJsonString!(R, pretty)(() @trusted { return value.toJson(); } (), m_level);
2021 			} else static assert(false, "Unsupported type: " ~ UT.stringof);
2022 		}
2023 
2024 		void writeStringSinkValue(Traits, T)(scope auto ref T value)
2025 		{
2026 			void sink(scope const(char)[] str) {
2027 				m_range.jsonEscape(str);
2028 			}
2029 
2030 			final class R {
2031 				void put(char ch) { put(() @trusted { return (&ch)[0 .. 1]; } ()); }
2032 				void put(scope const(char)[] str) { m_range.jsonEscape(str); }
2033 			}
2034 
2035 			m_range.put('"');
2036 			static if (__traits(compiles, value.toString((scope s) => sink(s)))) {
2037 				value.toString((scope s) => sink(s));
2038 			} else {
2039 				scope r = new R;
2040 				value.toString(r);
2041 			}
2042 			m_range.put('"');
2043 		}
2044 
2045 		private void startComposite()
2046 		{
2047 			static if (pretty) m_level++;
2048 			m_firstInComposite = true;
2049 		}
2050 
2051 		private void startCompositeEntry()
2052 		{
2053 			if (!m_firstInComposite) {
2054 				m_range.put(',');
2055 			} else {
2056 				m_firstInComposite = false;
2057 			}
2058 			static if (pretty) indent();
2059 		}
2060 
2061 		private void endComposite()
2062 		{
2063 			static if (pretty) {
2064 				m_level--;
2065 				if (!m_firstInComposite) indent();
2066 			}
2067 			m_firstInComposite = false;
2068 		}
2069 
2070 		private void indent()
2071 		{
2072 			m_range.put('\n');
2073 			foreach (i; 0 .. m_level) m_range.put('\t');
2074 		}
2075 	}
2076 
2077 	//
2078 	// deserialization
2079 	//
2080 	static if (isInputRange!(R)) {
2081 		private {
2082 			int m_line = 0;
2083 		}
2084 
2085 		void readDictionary(Traits)(scope void delegate(string) @safe entry_callback)
2086 		{
2087 			m_range.skipWhitespace(&m_line);
2088 			enforceJson(!m_range.empty && m_range.front == '{', "Expecting object.");
2089 			m_range.popFront();
2090 			bool first = true;
2091 			while(true) {
2092 				m_range.skipWhitespace(&m_line);
2093 				enforceJson(!m_range.empty, "Missing '}'.");
2094 				if (m_range.front == '}') {
2095 					m_range.popFront();
2096 					break;
2097 				} else if (!first) {
2098 					enforceJson(m_range.front == ',', "Expecting ',' or '}', not '"~m_range.front.to!string~"'.");
2099 					m_range.popFront();
2100 					m_range.skipWhitespace(&m_line);
2101 				} else first = false;
2102 
2103 				auto name = m_range.skipJsonString(&m_line);
2104 
2105 				m_range.skipWhitespace(&m_line);
2106 				enforceJson(!m_range.empty && m_range.front == ':', "Expecting ':', not '"~m_range.front.to!string~"'.");
2107 				m_range.popFront();
2108 
2109 				entry_callback(name);
2110 			}
2111 		}
2112 
2113 		void beginReadDictionaryEntry(Traits)(string name) {}
2114 		void endReadDictionaryEntry(Traits)(string name) {}
2115 
2116 		void readArray(Traits)(scope void delegate(size_t) @safe size_callback, scope void delegate() @safe entry_callback)
2117 		{
2118 			m_range.skipWhitespace(&m_line);
2119 			enforceJson(!m_range.empty && m_range.front == '[', "Expecting array.");
2120 			m_range.popFront();
2121 			bool first = true;
2122 			while(true) {
2123 				m_range.skipWhitespace(&m_line);
2124 				enforceJson(!m_range.empty, "Missing ']'.");
2125 				if (m_range.front == ']') {
2126 					m_range.popFront();
2127 					break;
2128 				} else if (!first) {
2129 					enforceJson(m_range.front == ',', "Expecting ',' or ']'.");
2130 					m_range.popFront();
2131 				} else first = false;
2132 
2133 				entry_callback();
2134 			}
2135 		}
2136 
2137 		void beginReadArrayEntry(Traits)(size_t index) {}
2138 		void endReadArrayEntry(Traits)(size_t index) {}
2139 
2140 		T readValue(Traits, T)()
2141 		{
2142 			m_range.skipWhitespace(&m_line);
2143 			static if (is(T == typeof(null))) { enforceJson(m_range.take(4).equal("null"), "Expecting 'null'."); return null; }
2144 			else static if (is(T == bool)) {
2145 				bool ret = m_range.front == 't';
2146 				string expected = ret ? "true" : "false";
2147 				foreach (ch; expected) {
2148 					enforceJson(m_range.front == ch, "Expecting 'true' or 'false'.");
2149 					m_range.popFront();
2150 				}
2151 				return ret;
2152 			} else static if (is(T : long)) {
2153 				bool is_float;
2154 				bool is_long_overflow;
2155 				auto num = m_range.skipNumber(is_float, is_long_overflow);
2156 				enforceJson(!is_float, "Expecting integer number.");
2157 				enforceJson(!is_long_overflow, num.to!string~" is too big for long.");
2158 				return to!T(num);
2159 			} else static if (is(T : BigInt)) {
2160 				bool is_float;
2161 				bool is_long_overflow;
2162 				auto num = m_range.skipNumber(is_float, is_long_overflow);
2163 				enforceJson(!is_float, "Expecting integer number.");
2164 				return BigInt(num);
2165 			} else static if (is(T : real)) {
2166 				bool is_float;
2167 				bool is_long_overflow;
2168 				auto num = m_range.skipNumber(is_float, is_long_overflow);
2169 				return to!T(num);
2170 			}
2171 			else static if (is(T == string) || is(T == const(char)[])) {
2172 				if (!m_range.empty && m_range.front == '[') {
2173 					return () @trusted { // appender
2174 						auto ret = appender!string();
2175 						readArray!Traits((sz) {}, () @trusted {
2176 							ret.put(m_range.skipJsonString(&m_line));
2177 						});
2178 						return ret.data;
2179 					} ();
2180 				} else return m_range.skipJsonString(&m_line);
2181 			}
2182 			else static if (isSomeString!T) return readValue!(Traits, string).to!T;
2183 			else static if (is(T == UUID)) return UUID(readValue!(Traits, string)());
2184 			else static if (is(T == Json)) return m_range.parseJson(&m_line);
2185 			else static if (is(T == JSONValue)) return cast(JSONValue)m_range.parseJson(&m_line);
2186 			else static if (isJsonSerializable!T) {
2187 				static if (!__traits(compiles, () @safe { return T.fromJson(Json.init); } ()))
2188 					pragma(msg, "Non-@safe toJson/fromJson methods are deprecated - annotate "~T.stringof~".fromJson() with @safe.");
2189 				return () @trusted { return T.fromJson(m_range.parseJson(&m_line)); } ();
2190 			} else static assert(false, "Unsupported type: " ~ T.stringof);
2191 		}
2192 
2193 		bool tryReadNull(Traits)()
2194 		{
2195 			m_range.skipWhitespace(&m_line);
2196 			if (m_range.front != 'n') return false;
2197 			foreach (ch; "null") {
2198 				enforceJson(m_range.front == ch, "Expecting 'null'.");
2199 				m_range.popFront();
2200 			}
2201 			assert(m_range.empty || m_range.front != 'l');
2202 			return true;
2203 		}
2204 
2205 		void skipValue() @safe
2206 		{
2207 			m_range.skipWhitespace(&m_line);
2208 			switch(m_range.front) {
2209 			case '[':
2210 				m_range.popFront();
2211 				bool first = true;
2212 				while(true) {
2213 					m_range.skipWhitespace(&m_line);
2214 					enforceJson(!m_range.empty, "Missing ']'.");
2215 					if (m_range.front == ']') {
2216 						m_range.popFront();
2217 						break;
2218 					} else if (!first) {
2219 						enforceJson(m_range.front == ',', "Expecting ',' or ']'.");
2220 						m_range.popFront();
2221 					} else first = false;
2222 					skipValue();
2223 				}
2224 				break;
2225 			case '{':
2226 				m_range.popFront();
2227 				bool first = true;
2228 				while(true) {
2229 					m_range.skipWhitespace(&m_line);
2230 					enforceJson(!m_range.empty, "Missing '}'.");
2231 					if (m_range.front == '}') {
2232 						m_range.popFront();
2233 						break;
2234 					} else if (!first) {
2235 						enforceJson(m_range.front == ',', "Expecting ',' or '}', not '"~m_range.front.to!string~"'.");
2236 						m_range.popFront();
2237 						m_range.skipWhitespace(&m_line);
2238 					} else first = false;
2239 
2240 					m_range.skipJsonString(&m_line);
2241 
2242 					m_range.skipWhitespace(&m_line);
2243 					enforceJson(!m_range.empty && m_range.front == ':', "Expecting ':', not '"~m_range.front.to!string~"'.");
2244 					m_range.popFront();
2245 
2246 					skipValue();
2247 				}
2248 				break;
2249 			case '"':
2250 				m_range.skipJsonString(&m_line);
2251 				break;
2252 			case '-':
2253 			case '0': .. case '9':
2254 				bool dummy; // ignore
2255 				m_range.skipNumber(dummy, dummy);
2256 				break;
2257 			case 't':
2258 				foreach (ch; "true") {
2259 					enforceJson(m_range.front == ch, "Expecting 'true'.");
2260 					m_range.popFront();
2261 				}
2262 				break;
2263 			case 'f':
2264 				foreach (ch; "false") {
2265 					enforceJson(m_range.front == ch, "Expecting 'false'.");
2266 					m_range.popFront();
2267 				}
2268 				break;
2269 			case 'n':
2270 				foreach (ch; "null") {
2271 					enforceJson(m_range.front == ch, "Expecting 'null'.");
2272 					m_range.popFront();
2273 				}
2274 				break;
2275 			default:
2276 				throw new JSONException("Expected start of object, array, string, number, boolean or null value, got"~m_range.front.to!string);
2277 			}
2278 			m_range.skipWhitespace(&m_line);
2279 		}
2280 	}
2281 }
2282 
2283 unittest {
2284 	static assert(doesSerializerSupportStringSink!(JsonStringSerializer!(Appender!string)));
2285 
2286 	auto app = appender!string;
2287 	auto ser = JsonStringSerializer!(Appender!string)(app);
2288 	static struct T1 { void toString(scope void delegate(scope const(char)[])) {} }
2289 	static struct T2 { void toString(R)(scope ref R dst) { dst.put('f'); dst.put("foo"); } }
2290 
2291 	ser.writeStringSinkValue!void(T1.init);
2292 	ser.writeStringSinkValue!void(T2.init);
2293 }
2294 
2295 /// Cloning JSON arrays
2296 unittest
2297 {
2298 	Json value = Json([ Json([ Json.emptyArray ]), Json.emptyArray ]).clone;
2299 
2300 	assert(value.length == 2);
2301 	assert(value[0].length == 1);
2302 	assert(value[0][0].length == 0);
2303 }
2304 
2305 unittest
2306 {
2307 	assert(serializeToJsonString(double.nan) == "null");
2308 	assert(serializeToJsonString(Json()) == "null");
2309 	assert(serializeToJsonString(Json(["bar":Json("baz"),"foo":Json()])) == `{"bar":"baz"}`);
2310 
2311 	struct Foo{Json bar = Json();}
2312 	Foo f;
2313 	assert(serializeToJsonString(f) == `{"bar":null}`);
2314 }
2315 
2316 /**
2317 	Writes the given JSON object as a JSON string into the destination range.
2318 
2319 	This function will convert the given JSON value to a string without adding
2320 	any white space between tokens (no newlines, no indentation and no padding).
2321 	The output size is thus minimized, at the cost of bad human readability.
2322 
2323 	Params:
2324 		dst   = References the string output range to which the result is written.
2325 		json  = Specifies the JSON value that is to be stringified.
2326 		level = Specifies the base amount of indentation for the output. Indentation is always
2327 				done using tab characters.
2328 
2329 	See_Also: Json.toString, writePrettyJsonString
2330 */
2331 void writeJsonString(R, bool pretty = false)(ref R dst, in Json json, size_t level = 0)
2332 @safe //	if( isOutputRange!R && is(ElementEncodingType!R == char) )
2333 {
2334 	final switch( json.type ){
2335 		case Json.Type.undefined: dst.put("null"); break;
2336 		case Json.Type.null_: dst.put("null"); break;
2337 		case Json.Type.bool_: dst.put(json.get!bool ? "true" : "false"); break;
2338 		case Json.Type.int_: formattedWrite(dst, "%d", json.get!long); break;
2339 		case Json.Type.bigInt: () @trusted { formattedWrite(dst, "%d", json.get!BigInt); } (); break;
2340 		case Json.Type.float_:
2341 			auto d = json.get!double;
2342 			if (d != d)
2343 				dst.put("null"); // JSON has no NaN value so set null
2344 			else
2345 				formattedWrite(dst, "%.16g", json.get!double);
2346 			break;
2347 		case Json.Type..string:
2348 			dst.put('\"');
2349 			jsonEscape(dst, json.get!string);
2350 			dst.put('\"');
2351 			break;
2352 		case Json.Type.array:
2353 			dst.put('[');
2354 			bool first = true;
2355 			foreach (ref const Json e; json.byValue) {
2356 				if( !first ) dst.put(",");
2357 				first = false;
2358 				static if (pretty) {
2359 					dst.put('\n');
2360 					foreach (tab; 0 .. level+1) dst.put('\t');
2361 				}
2362 				if (e.type == Json.Type.undefined) dst.put("null");
2363 				else writeJsonString!(R, pretty)(dst, e, level+1);
2364 			}
2365 			static if (pretty) {
2366 				if (json.length > 0) {
2367 					dst.put('\n');
2368 					foreach (tab; 0 .. level) dst.put('\t');
2369 				}
2370 			}
2371 			dst.put(']');
2372 			break;
2373 		case Json.Type.object:
2374 			dst.put('{');
2375 			bool first = true;
2376 			foreach (string k, ref const Json e; json.byKeyValue) {
2377 				if( e.type == Json.Type.undefined ) continue;
2378 				if( !first ) dst.put(',');
2379 				first = false;
2380 				static if (pretty) {
2381 					dst.put('\n');
2382 					foreach (tab; 0 .. level+1) dst.put('\t');
2383 				}
2384 				dst.put('\"');
2385 				jsonEscape(dst, k);
2386 				dst.put(pretty ? `": ` : `":`);
2387 				writeJsonString!(R, pretty)(dst, e, level+1);
2388 			}
2389 			static if (pretty) {
2390 				if (json.length > 0) {
2391 					dst.put('\n');
2392 					foreach (tab; 0 .. level) dst.put('\t');
2393 				}
2394 			}
2395 			dst.put('}');
2396 			break;
2397 	}
2398 }
2399 
2400 unittest {
2401 	auto a = Json.emptyObject;
2402 	a["a"] = Json.emptyArray;
2403 	a["b"] = Json.emptyArray;
2404 	a["b"] ~= Json(1);
2405 	a["b"] ~= Json.emptyObject;
2406 
2407 	assert(a.toString() == `{"a":[],"b":[1,{}]}` || a.toString() == `{"b":[1,{}],"a":[]}`);
2408 	assert(a.toPrettyString() ==
2409 `{
2410 	"a": [],
2411 	"b": [
2412 		1,
2413 		{}
2414 	]
2415 }`
2416 		|| a.toPrettyString() == `{
2417 	"b": [
2418 		1,
2419 		{}
2420 	],
2421 	"a": []
2422 }`);
2423 }
2424 
2425 unittest { // #735
2426 	auto a = Json.emptyArray;
2427 	a ~= "a";
2428 	a ~= Json();
2429 	a ~= "b";
2430 	a ~= null;
2431 	a ~= "c";
2432 	assert(a.toString() == `["a",null,"b",null,"c"]`);
2433 }
2434 
2435 unittest {
2436 	auto a = Json.emptyArray;
2437 	a ~= Json(1);
2438 	a ~= Json(2);
2439 	a ~= Json(3);
2440 	a ~= Json(4);
2441 	a ~= Json(5);
2442 
2443 	auto b = Json(a[0..a.length]);
2444 	assert(a == b);
2445 
2446 	auto c = Json(a[0..$]);
2447 	assert(a == c);
2448 	assert(b == c);
2449 
2450 	auto d = [Json(1),Json(2),Json(3)];
2451 	assert(d == a[0..a.length-2]);
2452 	assert(d == a[0..$-2]);
2453 }
2454 
2455 unittest {
2456 	auto j = Json(double.init);
2457 
2458 	assert(j.toString == "null"); // A double nan should serialize to null
2459 	j = 17.04f;
2460 	assert(j.toString == "17.04");	// A proper double should serialize correctly
2461 
2462 	double d;
2463 	deserializeJson(d, Json.undefined); // Json.undefined should deserialize to nan
2464 	assert(d != d);
2465 	deserializeJson(d, Json(null)); // Json.undefined should deserialize to nan
2466 	assert(d != d);
2467 }
2468 /**
2469 	Writes the given JSON object as a prettified JSON string into the destination range.
2470 
2471 	The output will contain newlines and indents to make the output human readable.
2472 
2473 	Params:
2474 		dst   = References the string output range to which the result is written.
2475 		json  = Specifies the JSON value that is to be stringified.
2476 		level = Specifies the base amount of indentation for the output. Indentation  is always
2477 				done using tab characters.
2478 
2479 	See_Also: Json.toPrettyString, writeJsonString
2480 */
2481 void writePrettyJsonString(R)(ref R dst, in Json json, int level = 0)
2482 //	if( isOutputRange!R && is(ElementEncodingType!R == char) )
2483 {
2484 	writeJsonString!(R, true)(dst, json, level);
2485 }
2486 
2487 
2488 /**
2489 	Helper function that escapes all Unicode characters in a JSON string.
2490 */
2491 string convertJsonToASCII(string json)
2492 {
2493 	auto ret = appender!string;
2494 	jsonEscape!true(ret, json);
2495 	return ret.data;
2496 }
2497 
2498 
2499 /// private
2500 private void jsonEscape(bool escape_unicode = false, R)(ref R dst, const(char)[] s)
2501 {
2502 	size_t startPos = 0;
2503 
2504 	void putInterval(size_t curPos)
2505 	{
2506 		if (curPos > startPos)
2507 			dst.put(s[startPos..curPos]);
2508 		startPos = curPos + 1;
2509 	}
2510 
2511 	for (size_t pos = 0; pos < s.length; pos++) {
2512 		immutable(char) ch = s[pos];
2513 
2514 		switch (ch) {
2515 			default:
2516 				static if (escape_unicode) {
2517 					if (ch <= 0x20 || ch >= 0x80)
2518 					{
2519 						putInterval(pos);
2520 						import std.utf : decode;
2521 						int len;
2522 						dchar codepoint = decode(s, pos);
2523 						/* codepoint is in BMP */
2524 						if(codepoint < 0x10000)
2525 						{
2526 							dst.formattedWrite("\\u%04X", codepoint);
2527 						}
2528 						/* not in BMP -> construct a UTF-16 surrogate pair */
2529 						else
2530 						{
2531 							int first, last;
2532 
2533 							codepoint -= 0x10000;
2534 							first = 0xD800 | ((codepoint & 0xffc00) >> 10);
2535 							last = 0xDC00 | (codepoint & 0x003ff);
2536 
2537 							dst.formattedWrite("\\u%04X\\u%04X", first, last);
2538 						}
2539 						startPos = pos;
2540 						pos -= 1;
2541 					}
2542 				}
2543 				else
2544 				{
2545 					if (ch < 0x20)
2546 					{
2547 						putInterval(pos);
2548 						dst.formattedWrite("\\u%04X", ch);
2549 					}
2550 				}
2551 				break;
2552 			case '\\': putInterval(pos); dst.put("\\\\"); break;
2553 			case '\r': putInterval(pos); dst.put("\\r"); break;
2554 			case '\n': putInterval(pos); dst.put("\\n"); break;
2555 			case '\t': putInterval(pos); dst.put("\\t"); break;
2556 			case '\"': putInterval(pos); dst.put("\\\""); break;
2557 			case '/':
2558 				// this avoids the sequence "</" in the output, which is prone
2559 				// to cross site scripting attacks when inserted into web pages
2560 				if (pos > 0 && s[pos-1] == '<')
2561 				{
2562 					putInterval(pos);
2563 					dst.put("\\/");
2564 				}
2565 				break;
2566 		}
2567 	}
2568 	// last interval
2569 	putInterval(s.length);
2570 }
2571 
2572 /// private
2573 private string jsonUnescape(R)(ref R range)
2574 {
2575 	auto ret = appender!string();
2576 	while(!range.empty){
2577 		auto ch = range.front;
2578 		switch( ch ){
2579 			case '"': return ret.data;
2580 			case '\\':
2581 				range.popFront();
2582 				enforceJson(!range.empty, "Unterminated string escape sequence.");
2583 				switch(range.front){
2584 					default: enforceJson(false, "Invalid string escape sequence."); break;
2585 					case '"': ret.put('\"'); range.popFront(); break;
2586 					case '\\': ret.put('\\'); range.popFront(); break;
2587 					case '/': ret.put('/'); range.popFront(); break;
2588 					case 'b': ret.put('\b'); range.popFront(); break;
2589 					case 'f': ret.put('\f'); range.popFront(); break;
2590 					case 'n': ret.put('\n'); range.popFront(); break;
2591 					case 'r': ret.put('\r'); range.popFront(); break;
2592 					case 't': ret.put('\t'); range.popFront(); break;
2593 					case 'u':
2594 
2595 						dchar decode_unicode_escape() {
2596 							enforceJson(range.front == 'u');
2597 							range.popFront();
2598 							dchar uch = 0;
2599 							foreach( i; 0 .. 4 ){
2600 								uch *= 16;
2601 								enforceJson(!range.empty, "Unicode sequence must be '\\uXXXX'.");
2602 								auto dc = range.front;
2603 								range.popFront();
2604 
2605 								if( dc >= '0' && dc <= '9' ) uch += dc - '0';
2606 								else if( dc >= 'a' && dc <= 'f' ) uch += dc - 'a' + 10;
2607 								else if( dc >= 'A' && dc <= 'F' ) uch += dc - 'A' + 10;
2608 								else enforceJson(false, "Unicode sequence must be '\\uXXXX'.");
2609 							}
2610 							return uch;
2611 						}
2612 
2613 						auto uch = decode_unicode_escape();
2614 
2615 						if(0xD800 <= uch && uch <= 0xDBFF) {
2616 							/* surrogate pair */
2617 							range.popFront(); // backslash '\'
2618 							auto uch2 = decode_unicode_escape();
2619 							enforceJson(0xDC00 <= uch2 && uch2 <= 0xDFFF, "invalid Unicode");
2620 							{
2621 								/* valid second surrogate */
2622 								uch =
2623 									((uch - 0xD800) << 10) +
2624 										(uch2 - 0xDC00) +
2625 										0x10000;
2626 							}
2627 						}
2628 						ret.put(uch);
2629 						break;
2630 				}
2631 				break;
2632 			default:
2633 				ret.put(ch);
2634 				range.popFront();
2635 				break;
2636 		}
2637 	}
2638 	return ret.data;
2639 }
2640 
2641 private auto skipNumber(R)(ref R s, out bool is_float, out bool is_long_overflow) @safe
2642 	if (isNarrowString!R)
2643 {
2644 	auto r = s.representation;
2645 	version (assert) auto rEnd = (() @trusted => r.ptr + r.length - 1)();
2646 	auto res = skipNumber(r, is_float, is_long_overflow);
2647 	version (assert) assert(rEnd == (() @trusted => r.ptr + r.length - 1)()); // check nothing taken off the end
2648 	s = s[$ - r.length .. $];
2649 	return res.assumeUTF();
2650 }
2651 
2652 /// private
2653 private auto skipNumber(R)(ref R s, out bool is_float, out bool is_long_overflow)
2654 	if (!isNarrowString!R && isForwardRange!R)
2655 {
2656 	auto sOrig = s.save;
2657 	size_t idx = 0;
2658 	is_float = false;
2659 	is_long_overflow = false;
2660 	ulong int_part = 0;
2661 	if (s.front == '-') {
2662 		s.popFront(); ++idx;
2663 	}
2664 	if (s.front == '0') {
2665 		s.popFront(); ++idx;
2666 	}
2667 	else {
2668 		enforceJson(isDigit(s.front), "Digit expected at beginning of number.");
2669 		int_part = s.front - '0';
2670 		s.popFront(); ++idx;
2671 		while( !s.empty && isDigit(s.front) ) {
2672 			if (!is_long_overflow) {
2673 				auto dig = s.front - '0';
2674 				if ((long.max / 10) > int_part || ((long.max / 10) == int_part && (long.max % 10) >= dig)) {
2675 					int_part *= 10;
2676 					int_part += dig;
2677 				}
2678 				else {
2679 					is_long_overflow = true;
2680 				}
2681 			}
2682 			s.popFront(); ++idx;
2683 		}
2684 	}
2685 
2686 	if( !s.empty && s.front == '.' ) {
2687 		s.popFront(); ++idx;
2688 		is_float = true;
2689 		while( !s.empty && isDigit(s.front) ) {
2690 			s.popFront(); ++idx;
2691 		}
2692 	}
2693 
2694 	if( !s.empty && (s.front == 'e' || s.front == 'E') ) {
2695 		s.popFront(); ++idx;
2696 		is_float = true;
2697 		if( !s.empty && (s.front == '+' || s.front == '-') ) {
2698 			s.popFront(); ++idx;
2699 		}
2700 		enforceJson( !s.empty && isDigit(s.front), "Expected exponent." ~ sOrig.takeExactly(idx).to!string);
2701 		s.popFront(); ++idx;
2702 		while( !s.empty && isDigit(s.front) ) {
2703 			s.popFront(); ++idx;
2704 		}
2705 	}
2706 
2707 	return sOrig.takeExactly(idx);
2708 }
2709 
2710 unittest
2711 {
2712 	import std.meta : AliasSeq;
2713 	// test for string and for a simple range
2714 	foreach (foo; AliasSeq!(to!string, map!"a")) {
2715 		auto test_1 = foo("9223372036854775806"); // lower then long.max
2716 		auto test_2 = foo("9223372036854775807"); // long.max
2717 		auto test_3 = foo("9223372036854775808"); // greater then long.max
2718 		bool is_float;
2719 		bool is_long_overflow;
2720 		test_1.skipNumber(is_float, is_long_overflow);
2721 		assert(!is_long_overflow);
2722 		test_2.skipNumber(is_float, is_long_overflow);
2723 		assert(!is_long_overflow);
2724 		test_3.skipNumber(is_float, is_long_overflow);
2725 		assert(is_long_overflow);
2726 	}
2727 }
2728 
2729 /// private
2730 private string skipJsonString(R)(ref R s, int* line = null)
2731 {
2732 	// TODO: count or disallow any newlines inside of the string
2733 	enforceJson(!s.empty && s.front == '"', "Expected '\"' to start string.");
2734 	s.popFront();
2735 	string ret = jsonUnescape(s);
2736 	enforceJson(!s.empty && s.front == '"', "Expected '\"' to terminate string.");
2737 	s.popFront();
2738 	return ret;
2739 }
2740 
2741 /// private
2742 private void skipWhitespace(R)(ref R s, int* line = null)
2743 {
2744 	while (!s.empty) {
2745 		switch (s.front) {
2746 			default: return;
2747 			case ' ', '\t': s.popFront(); break;
2748 			case '\n':
2749 				s.popFront();
2750 				if (!s.empty && s.front == '\r') s.popFront();
2751 				if (line) (*line)++;
2752 				break;
2753 			case '\r':
2754 				s.popFront();
2755 				if (!s.empty && s.front == '\n') s.popFront();
2756 				if (line) (*line)++;
2757 				break;
2758 		}
2759 	}
2760 }
2761 
2762 private bool isDigit(dchar ch) @safe nothrow pure { return ch >= '0' && ch <= '9'; }
2763 
2764 private string underscoreStrip(string field_name)
2765 @safe nothrow pure {
2766 	if( field_name.length < 1 || field_name[$-1] != '_' ) return field_name;
2767 	else return field_name[0 .. $-1];
2768 }
2769 
2770 /// private
2771 package template isJsonSerializable(T) { enum isJsonSerializable = is(typeof(T.init.toJson()) : Json) && is(typeof(T.fromJson(Json())) : T); }
2772 
2773 private void enforceJson(string file = __FILE__, size_t line = __LINE__)(bool cond, lazy string message = "JSON exception")
2774 {
2775 	import std.exception : enforce;
2776 	enforce!JSONException(cond, message, file, line);
2777 }
2778 
2779 private void enforceJson(string file = __FILE__, size_t line = __LINE__)(bool cond, lazy string message, string err_file, int err_line)
2780 {
2781 	import std.exception : enforce;
2782 	enforce!JSONException(cond, format("%s(%s): Error: %s", err_file, err_line+1, message), file, line);
2783 }
2784 
2785 private void enforceJson(string file = __FILE__, size_t line = __LINE__)(bool cond, lazy string message, string err_file, int* err_line)
2786 {
2787 	enforceJson!(file, line)(cond, message, err_file, err_line ? *err_line : -1);
2788 }
2789 
2790 private auto trustedRange(R)(R range)
2791 {
2792 	static struct Rng {
2793 		private R range;
2794 		@property bool empty() @trusted { return range.empty; }
2795 		@property auto front() @trusted { return range.front; }
2796 		void popFront() @trusted { range.popFront(); }
2797 	}
2798 	return Rng(range);
2799 }
2800 
2801 // test for vibe.utils.DictionaryList
2802 @safe unittest {
2803 	import vibe.utils.dictionarylist;
2804 
2805 	static assert(isCustomSerializable!(DictionaryList!int));
2806 
2807 	DictionaryList!(int, false) b;
2808 	b.addField("a", 1);
2809 	b.addField("A", 2);
2810 	auto app = appender!string();
2811 	serializeToJson(app, b);
2812 	assert(app.data == `[{"key":"a","value":1},{"key":"A","value":2}]`, app.data);
2813 
2814 	DictionaryList!(int, true, 2) c;
2815 	c.addField("a", 1);
2816 	c.addField("b", 2);
2817 	c.addField("a", 3);
2818 	c.remove("b");
2819 	auto appc = appender!string();
2820 	serializeToJson(appc, c);
2821 	assert(appc.data == `[{"key":"a","value":1},{"key":"a","value":3}]`, appc.data);
2822 }
2823 
2824 // make sure Json is usable for CTFE
2825 @safe unittest {
2826 	static assert(is(typeof({
2827 		struct Test {
2828 			Json object_ = Json.emptyObject;
2829 			Json array   = Json.emptyArray;
2830 		}
2831 	})), "CTFE for Json type failed.");
2832 
2833 	static Json test() {
2834 		Json j;
2835 		j = Json(42);
2836 		j = Json([Json(true)]);
2837 		j = Json(["foo": Json(null)]);
2838 		j = Json("foo");
2839 		return j;
2840 	}
2841 	enum j = test();
2842 	static assert(j == Json("foo"));
2843 }
2844 
2845 @safe unittest { // XSS prevention
2846 	assert(Json("</script>some/path").toString() == `"<\/script>some/path"`);
2847 	assert(serializeToJsonString("</script>some/path") == `"<\/script>some/path"`);
2848 }
2849 
2850 @system unittest { // Recursive structures
2851 	static struct Bar { Bar[] foos; int i; }
2852 	auto b = deserializeJson!Bar(`{"i":1,"foos":[{"foos":[],"i":2}]}`);
2853 	assert(b.i == 1);
2854 	assert(b.foos.length == 1);
2855 	assert(b.foos[0].i == 2);
2856 	assert(b.foos[0].foos.length == 0);
2857 }
2858 
2859 @safe unittest { // Json <-> std.json.JSONValue
2860 	auto astr = `{
2861 		"null": null,
2862 		"string": "Hello",
2863 		"integer": 123456,
2864 		"uinteger": 18446744073709551614,
2865 		"float": 12.34,
2866 		"object": { "hello": "world" },
2867 		"array": [1, 2, "string"],
2868 		"true": true,
2869 		"false": false
2870 	}`;
2871 	auto a = parseJsonString(astr);
2872 
2873 	// test JSONValue -> Json conversion
2874 	assert(Json(cast(JSONValue)a) == a);
2875 
2876 	// test Json -> JSONValue conversion
2877 	auto v = cast(JSONValue)a;
2878 	assert(deserializeJson!JSONValue(serializeToJson(v)) == v);
2879 
2880 	// test JSON strint <-> JSONValue serialization
2881 	assert(deserializeJson!JSONValue(astr) == v);
2882 	assert(parseJsonString(serializeToJsonString(v)) == a);
2883 
2884 	// test using std.conv for the conversion
2885 	import std.conv : to;
2886 	assert(a.to!JSONValue.to!Json == a);
2887 	assert(to!Json(to!JSONValue(a)) == a);
2888 }
2889 
2890 @safe unittest { // issue #2150 - serialization of const/mutable strings + wide character strings
2891 	assert(serializeToJson(cast(const(char)[])"foo") == Json("foo"));
2892 	assert(serializeToJson("foo".dup) == Json("foo"));
2893 	assert(deserializeJson!string(Json("foo")) == "foo");
2894 	assert(deserializeJson!string(Json([Json("f"), Json("o"), Json("o")])) == "foo");
2895 	assert(serializeToJsonString(cast(const(char)[])"foo") == "\"foo\"");
2896 	assert(deserializeJson!string("\"foo\"") == "foo");
2897 
2898 	assert(serializeToJson(cast(const(wchar)[])"foo"w) == Json("foo"));
2899 	assert(serializeToJson("foo"w.dup) == Json("foo"));
2900 	assert(deserializeJson!wstring(Json("foo")) == "foo");
2901 	assert(deserializeJson!wstring(Json([Json("f"), Json("o"), Json("o")])) == "foo");
2902 	assert(serializeToJsonString(cast(const(wchar)[])"foo"w) == "\"foo\"");
2903 	assert(deserializeJson!wstring("\"foo\"") == "foo");
2904 
2905 	assert(serializeToJson(cast(const(dchar)[])"foo"d) == Json("foo"));
2906 	assert(serializeToJson("foo"d.dup) == Json("foo"));
2907 	assert(deserializeJson!dstring(Json("foo")) == "foo");
2908 	assert(deserializeJson!dstring(Json([Json("f"), Json("o"), Json("o")])) == "foo");
2909 	assert(serializeToJsonString(cast(const(dchar)[])"foo"d) == "\"foo\"");
2910 	assert(deserializeJson!dstring("\"foo\"") == "foo");
2911 }
2912 
2913 
2914 unittest { // issue #1647 - JSON deserializeJson throws exception on unknown input fields
2915 	struct S {
2916 		string foo;
2917 	}
2918 	S expected = S("bar");
2919 	assert(deserializeJson!S(`{"foo":"bar","baz":"bam"}`) == expected);
2920 }