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