1 /**
2  * JSON encoding.
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <ae@cy.md>
12  */
13 
14 module ae.utils.json;
15 
16 import std.exception;
17 import std.math : isFinite;
18 import std.string;
19 import std.traits;
20 import std.typecons;
21 
22 import ae.utils.appender;
23 import ae.utils.array : isIdentical;
24 import ae.utils.exception;
25 import ae.utils.functor.primitives : functor;
26 import ae.utils.meta;
27 import ae.utils.textout;
28 
29 // ************************************************************************
30 
31 /// JSON serialization / deserialization options
32 struct JsonOptions
33 {
34 	/// What to do with associative arrays with non-string keys
35 	enum NonStringKeys
36 	{
37 		/// Fail compilation.
38 		error,
39 
40 		/// Serialize keys as-is - results in non-compliant JSON.
41 		asIs,
42 
43 		/// Serialize keys as strings.
44 		/// Note that this may result in multiple levels of quoting.
45 		stringify,
46 	}
47 	NonStringKeys nonStringKeys = NonStringKeys.error; /// ditto
48 }
49 
50 // ************************************************************************
51 
52 /// Basic JSON writer.
53 struct JsonWriter(Output)
54 {
55 	/// You can set this to something to e.g. write to another buffer.
56 	Output output;
57 
58 	private void putChars(S...)(S strings)
59 	{
60 		static if (is(typeof(output.putEx(strings))))
61 			output.putEx(strings);
62 		else
63 			foreach (str; strings)
64 				static if (is(typeof(output.put(str))))
65 					output.put(str);
66 				else
67 					foreach (dchar c; str)
68 					{
69 						alias C = char; // TODO: get char type of output
70 						C[4 / C.sizeof] buf = void;
71 						auto size = encode(buf, c);
72 						output.put(buf[0..size]);
73 					}
74 	}
75 
76 	/// Write a string literal.
77 	private void putString(C)(in C[] s)
78 	{
79 		// TODO: escape Unicode characters?
80 		// TODO: Handle U+2028 and U+2029 ( http://timelessrepo.com/json-isnt-a-javascript-subset )
81 
82 		output.putEx('"');
83 		auto start = s.ptr, p = start, end = start+s.length;
84 
85 		while (p < end)
86 		{
87 			auto c = *p++;
88 			if (c < Escapes.escaped.length && Escapes.escaped[c])
89 			{
90 				putChars(start[0..p-start-1], Escapes.chars[c]);
91 				start = p;
92 			}
93 		}
94 
95 		putChars(start[0..p-start], '"');
96 	}
97 
98 	/// Write a value of a simple type.
99 	void putValue(T)(T v)
100 	{
101 		static if (is(typeof(v is null)))
102 			if (v is null)
103 				return output.put("null");
104 		static if (is(T == typeof(null)))
105 			return output.put("null");
106 		else
107 		static if (isSomeString!T)
108 			putString(v);
109 		else
110 		static if (isSomeChar!(Unqual!T))
111 			return putString((&v)[0..1]);
112 		else
113 		static if (is(Unqual!T == bool))
114 			return output.put(v ? "true" : "false");
115 		else
116 		static if (is(Unqual!T : long))
117 			return .put(output, v);
118 		else
119 		static if (is(Unqual!T : real))
120 			if (v.isFinite)
121 				return output.putFP(v);
122 			else
123 				return putString(v.to!string);
124 		else
125 			static assert(0, "Don't know how to write " ~ T.stringof);
126 	}
127 
128 	void beginArray()
129 	{
130 		output.putEx('[');
131 	} ///
132 
133 	void endArray()
134 	{
135 		output.putEx(']');
136 	} ///
137 
138 	void beginObject()
139 	{
140 		output.putEx('{');
141 	} ///
142 
143 	void endObject()
144 	{
145 		output.putEx('}');
146 	} ///
147 
148 	void endKey()
149 	{
150 		output.putEx(':');
151 	} ///
152 
153 	void putComma()
154 	{
155 		output.putEx(',');
156 	} ///
157 }
158 
159 /// JSON writer with indentation.
160 struct PrettyJsonWriter(Output, alias indent = '\t', alias newLine = '\n', alias pad = ' ')
161 {
162 	JsonWriter!Output jsonWriter; /// Underlying writer.
163 	alias jsonWriter this;
164 
165 	private bool indentPending;
166 	private uint indentLevel;
167 
168 	private void putIndent()
169 	{
170 		if (indentPending)
171 		{
172 			foreach (n; 0..indentLevel)
173 				output.putEx(indent);
174 			indentPending = false;
175 		}
176 	}
177 
178 	private void putNewline()
179 	{
180 		if (!indentPending)
181 		{
182 			output.putEx(newLine);
183 			indentPending = true;
184 		}
185 	}
186 
187 	void putValue(T)(T v)
188 	{
189 		putIndent();
190 		jsonWriter.putValue(v);
191 	} ///
192 
193 	void beginArray()
194 	{
195 		putIndent();
196 		jsonWriter.beginArray();
197 		indentLevel++;
198 		putNewline();
199 	} ///
200 
201 	void endArray()
202 	{
203 		indentLevel--;
204 		putNewline();
205 		putIndent();
206 		jsonWriter.endArray();
207 	} ///
208 
209 	void beginObject()
210 	{
211 		putIndent();
212 		jsonWriter.beginObject();
213 		indentLevel++;
214 		putNewline();
215 	} ///
216 
217 	void endObject()
218 	{
219 		indentLevel--;
220 		putNewline();
221 		putIndent();
222 		jsonWriter.endObject();
223 	} ///
224 
225 	void endKey()
226 	{
227 		output.putEx(pad, ':', pad);
228 	} ///
229 
230 	void putComma()
231 	{
232 		jsonWriter.putComma();
233 		putNewline();
234 	} ///
235 }
236 
237 /// Abstract JSON serializer based on `Writer`.
238 struct CustomJsonSerializer(Writer, JsonOptions options = JsonOptions.init)
239 {
240 	Writer writer; /// Output.
241 
242 	/// Put a serializable value.
243 	void put(T)(auto ref T v)
244 	{
245 		static if (__traits(hasMember, T, "toJSON"))
246 			static if (is(typeof(v.toJSON())))
247 				put(v.toJSON());
248 			else
249 				v.toJSON((&this).functor!((self, ref j) => self.put(j)));
250 		else
251 		static if (is(T X == Nullable!X))
252 			if (v.isNull)
253 				writer.putValue(null);
254 			else
255 				put(v.get);
256 		else
257 		static if (is(T == enum))
258 			put(to!string(v));
259 		else
260 		static if (isSomeString!T || is(Unqual!T : real))
261 			writer.putValue(v);
262 		else
263 		static if (is(T == typeof(null)))
264 			writer.putValue(null);
265 		else
266 		static if (is(T U : U[]))
267 		{
268 			writer.beginArray();
269 			if (v.length)
270 			{
271 				put(v[0]);
272 				foreach (i; v[1..$])
273 				{
274 					writer.putComma();
275 					put(i);
276 				}
277 			}
278 			writer.endArray();
279 		}
280 		else
281 		static if (isTuple!T)
282 		{
283 			// TODO: serialize as object if tuple has names
284 			enum N = v.expand.length;
285 			static if (N == 0)
286 				return;
287 			else
288 			static if (N == 1)
289 				put(v.expand[0]);
290 			else
291 			{
292 				writer.beginArray();
293 				foreach (n; rangeTuple!N)
294 				{
295 					static if (n)
296 						writer.putComma();
297 					put(v.expand[n]);
298 				}
299 				writer.endArray();
300 			}
301 		}
302 		else
303 		static if (is(typeof(T.init.keys)) && is(typeof(T.init.values)))
304 		{
305 			writer.beginObject();
306 			bool first = true;
307 			foreach (key, value; v)
308 			{
309 				if (!first)
310 					writer.putComma();
311 				else
312 					first = false;
313 				static if (is(typeof({string s = T.init.keys[0];})))
314 					writer.putValue(key);
315 				else
316 					static if (options.nonStringKeys == JsonOptions.NonStringKeys.asIs)
317 						put(key);
318 					else
319 					static if (options.nonStringKeys == JsonOptions.NonStringKeys.stringify)
320 						writer.putValue(key.toJson!options);
321 					else
322 						static assert(false, "Cannot serialize associative array with non-string key " ~ K.stringof);
323 				writer.endKey();
324 				put(value);
325 			}
326 			writer.endObject();
327 		}
328 		else
329 		static if (is(T==JSONFragment))
330 			writer.output.put(v.json);
331 		else
332 		static if (is(T==struct))
333 		{
334 			writer.beginObject();
335 			bool first = true;
336 			foreach (i, ref field; v.tupleof)
337 			{
338 				static if (!doSkipSerialize!(T, v.tupleof[i].stringof[2..$]))
339 				{
340 					static if (hasAttribute!(JSONOptional, v.tupleof[i]))
341 						if (isIdentical(v.tupleof[i], T.init.tupleof[i]))
342 							continue;
343 					if (!first)
344 						writer.putComma();
345 					else
346 						first = false;
347 					writer.putValue(getJsonName!(T, v.tupleof[i].stringof[2..$]));
348 					writer.endKey();
349 					put(field);
350 				}
351 			}
352 			writer.endObject();
353 		}
354 		else
355 		static if (is(typeof(*v)))
356 		{
357 			if (v)
358 				put(*v);
359 			else
360 				writer.putValue(null);
361 		}
362 		else
363 			static assert(0, "Can't serialize " ~ T.stringof ~ " to JSON");
364 	}
365 }
366 
367 /// JSON serializer with `StringBuilder` output.
368 alias JsonSerializer = CustomJsonSerializer!(JsonWriter!StringBuilder);
369 
370 private struct Escapes
371 {
372 	static immutable  string[256] chars;
373 	static immutable bool[256] escaped;
374 
375 	shared static this()
376 	{
377 		import std.string : format;
378 
379 		escaped[] = true;
380 		foreach (c; 0..256)
381 			if (c=='\\')
382 				chars[c] = `\\`;
383 			else
384 			if (c=='\"')
385 				chars[c] = `\"`;
386 			else
387 			if (c=='\b')
388 				chars[c] = `\b`;
389 			else
390 			if (c=='\f')
391 				chars[c] = `\f`;
392 			else
393 			if (c=='\n')
394 				chars[c] = `\n`;
395 			else
396 			if (c=='\r')
397 				chars[c] = `\r`;
398 			else
399 			if (c=='\t')
400 				chars[c] = `\t`;
401 			else
402 			if (c<'\x20' || c == '\x7F' || c=='<' || c=='>' || c=='&')
403 				chars[c] = format(`\u%04x`, c);
404 			else
405 				chars[c] = [cast(char)c],
406 				escaped[c] = false;
407 	}
408 }
409 
410 // ************************************************************************
411 
412 /// Serialize `T` to JSON, and return the result as a string.
413 string toJson(T)(auto ref T v)
414 {
415 	JsonSerializer serializer;
416 	serializer.put(v);
417 	return serializer.writer.output.get();
418 }
419 
420 /// ditto
421 string toJson(JsonOptions options, T)(auto ref T v)
422 {
423 	CustomJsonSerializer!(JsonWriter!StringBuilder, options) serializer;
424 	serializer.put(v);
425 	return serializer.writer.output.get();
426 }
427 
428 ///
429 debug(ae_unittest) unittest
430 {
431 	struct X { int a; string b; }
432 	X x = {17, "aoeu"};
433 	assert(toJson(x) == `{"a":17,"b":"aoeu"}`, toJson(x));
434 	int[] arr = [1,5,7];
435 	assert(toJson(arr) == `[1,5,7]`);
436 	assert(toJson(true) == `true`);
437 
438 	assert(toJson(tuple()) == ``);
439 	assert(toJson(tuple(42)) == `42`);
440 	assert(toJson(tuple(42, "banana")) == `[42,"banana"]`);
441 }
442 
443 debug(ae_unittest) unittest
444 {
445 	struct A
446 	{
447 	}
448 
449 	struct B
450 	{
451 		A[] a;
452 		deprecated alias a this;
453 		JSONFragment toJSON() const { return JSONFragment(`null`); }
454 	}
455 
456 	B b;
457 	b.toJson();
458 }
459 
460 // ************************************************************************
461 
462 /// Serialize `T` to a pretty (indented) JSON string.
463 string toPrettyJson(T)(T v)
464 {
465 	CustomJsonSerializer!(PrettyJsonWriter!StringBuilder) serializer;
466 	serializer.put(v);
467 	return serializer.writer.output.get();
468 }
469 
470 /// ditto
471 string toPrettyJson(JsonOptions options, T)(T v)
472 {
473 	CustomJsonSerializer!(PrettyJsonWriter!StringBuilder, options) serializer;
474 	serializer.put(v);
475 	return serializer.writer.output.get();
476 }
477 
478 ///
479 debug(ae_unittest) unittest
480 {
481 	struct X { int a; string b; int[] c, d; }
482 	X x = {17, "aoeu", [1, 2, 3]};
483 	assert(toPrettyJson(x) ==
484 `{
485 	"a" : 17,
486 	"b" : "aoeu",
487 	"c" : [
488 		1,
489 		2,
490 		3
491 	],
492 	"d" : [
493 	]
494 }`, toPrettyJson(x));
495 }
496 
497 // ************************************************************************
498 
499 import std.ascii;
500 import std.utf;
501 import std.conv;
502 
503 import ae.utils.text;
504 
505 private struct JsonParser(C, JsonOptions options = JsonOptions.init)
506 {
507 	C[] s;
508 	size_t p;
509 
510 	Unqual!C next()
511 	{
512 		enforce(p < s.length, "Out of data while parsing JSON stream");
513 		return s[p++];
514 	}
515 
516 	string readN(uint n)
517 	{
518 		string r;
519 		for (int i=0; i<n; i++)
520 			r ~= next();
521 		return r;
522 	}
523 
524 	Unqual!C peek()
525 	{
526 		enforce(p < s.length, "Out of data while parsing JSON stream");
527 		return s[p];
528 	}
529 
530 	@property bool eof() { return p == s.length; }
531 
532 	void skipWhitespace()
533 	{
534 		while (isWhite(peek()))
535 			p++;
536 	}
537 
538 	void expect(C c)
539 	{
540 		auto n = next();
541 		enforce(n==c, text("Expected ", c, ", got ", n));
542 	}
543 
544 	void read(T)(ref T value)
545 	{
546 		static if (is(T == typeof(null)))
547 			value = readNull();
548 		else
549 		static if (is(T X == Nullable!X))
550 			readNullable!X(value);
551 		else
552 		static if (is(T==enum))
553 			value = readEnum!(T)();
554 		else
555 		static if (isSomeString!T)
556 			value = readString().to!T;
557 		else
558 		static if (is(T==bool))
559 			value = readBool();
560 		else
561 		static if (is(T : real))
562 			value = readNumber!(T)();
563 		else
564 		static if (isDynamicArray!T)
565 			value = readArray!(typeof(T.init[0]))();
566 		else
567 		static if (isStaticArray!T)
568 			readStaticArray(value);
569 		else
570 		static if (isTuple!T)
571 			readTuple!T(value);
572 		else
573 		static if (is(typeof(T.init.keys)) && is(typeof(T.init.values)))
574 			readAA!(T)(value);
575 		else
576 		static if (is(T==JSONFragment))
577 		{
578 			auto start = p;
579 			skipValue();
580 			value = JSONFragment(s[start..p]);
581 		}
582 		else
583 		static if (is(T U : U*))
584 			value = readPointer!T();
585 		else
586 		static if (__traits(hasMember, T, "fromJSON"))
587 		{
588 			alias Q = Parameters!(T.fromJSON)[0];
589 			Q tempValue;
590 			read!Q(tempValue);
591 			static if (is(typeof(value = T.fromJSON(tempValue))))
592 				value = T.fromJSON(tempValue);
593 			else
594 			{
595 				import core.lifetime : move;
596 				auto convertedValue = T.fromJSON(tempValue);
597 				move(convertedValue, value);
598 			}
599 		}
600 		else
601 		static if (is(T==struct))
602 			readObject!(T)(value);
603 		else
604 			static assert(0, "Can't decode " ~ T.stringof ~ " from JSON");
605 	}
606 
607 	void readTuple(T)(ref T value)
608 	{
609 		// TODO: serialize as object if tuple has names
610 		enum N = T.expand.length;
611 		static if (N == 0)
612 			return;
613 		else
614 		static if (N == 1)
615 			read(value.expand[0]);
616 		else
617 		{
618 			expect('[');
619 			foreach (n, ref f; value.expand)
620 			{
621 				static if (n)
622 					expect(',');
623 				read(f);
624 			}
625 			expect(']');
626 		}
627 	}
628 
629 	typeof(null) readNull()
630 	{
631 		expect('n');
632 		expect('u');
633 		expect('l');
634 		expect('l');
635 		return null;
636 	}
637 
638 	void readNullable(T)(ref Nullable!T value)
639 	{
640 		skipWhitespace();
641 		if (peek() == 'n')
642 		{
643 			readNull();
644 			value = Nullable!T();
645 		}
646 		else
647 		{
648 			if (value.isNull)
649 			{
650 				T subvalue;
651 				read!T(subvalue);
652 				value = subvalue;
653 			}
654 			else
655 				read!T(value.get());
656 		}
657 	}
658 
659 	C[] readSimpleString() /// i.e. without escapes
660 	{
661 		skipWhitespace();
662 		expect('"');
663 		auto start = p;
664 		while (true)
665 		{
666 			auto c = next();
667 			if (c=='"')
668 				break;
669 			else
670 			if (c=='\\')
671 				throw new Exception("Unexpected escaped character");
672 		}
673 		return s[start..p-1];
674 	}
675 
676 	C[] readString()
677 	{
678 		skipWhitespace();
679 		auto c = peek();
680 		if (c == '"')
681 		{
682 			next(); // '"'
683 			C[] result;
684 			auto start = p;
685 			while (true)
686 			{
687 				c = next();
688 				if (c=='"')
689 					break;
690 				else
691 				if (c=='\\')
692 				{
693 					result ~= s[start..p-1];
694 					switch (next())
695 					{
696 						case '"':  result ~= '"'; break;
697 						case '/':  result ~= '/'; break;
698 						case '\\': result ~= '\\'; break;
699 						case 'b':  result ~= '\b'; break;
700 						case 'f':  result ~= '\f'; break;
701 						case 'n':  result ~= '\n'; break;
702 						case 'r':  result ~= '\r'; break;
703 						case 't':  result ~= '\t'; break;
704 						case 'u':
705 						{
706 							wstring buf;
707 							goto Unicode_start;
708 
709 							while (s[p..$].startsWith(`\u`))
710 							{
711 								p+=2;
712 							Unicode_start:
713 								buf ~= cast(wchar)fromHex!ushort(readN(4));
714 							}
715 							result ~= buf.to!(C[]);
716 							break;
717 						}
718 						default: enforce(false, "Unknown escape");
719 					}
720 					start = p;
721 				}
722 			}
723 			result ~= s[start..p-1];
724 			return result;
725 		}
726 		else
727 		if (isDigit(c) || c=='-') // For languages that don't distinguish numeric strings from numbers
728 		{
729 			static immutable bool[256] numeric =
730 			[
731 				'0':true,
732 				'1':true,
733 				'2':true,
734 				'3':true,
735 				'4':true,
736 				'5':true,
737 				'6':true,
738 				'7':true,
739 				'8':true,
740 				'9':true,
741 				'.':true,
742 				'-':true,
743 				'+':true,
744 				'e':true,
745 				'E':true,
746 			];
747 
748 			auto start = p;
749 			while (numeric[c = peek()])
750 				p++;
751 			return s[start..p].dup;
752 		}
753 		else
754 		{
755 			foreach (n; "null")
756 				expect(n);
757 			return null;
758 		}
759 	}
760 
761 	bool readBool()
762 	{
763 		skipWhitespace();
764 		if (peek()=='t')
765 		{
766 			enforce(readN(4) == "true", "Bad boolean");
767 			return true;
768 		}
769 		else
770 		if (peek()=='f')
771 		{
772 			enforce(readN(5) == "false", "Bad boolean");
773 			return false;
774 		}
775 		else
776 		{
777 			ubyte i = readNumber!ubyte();
778 			enforce(i < 2, "Bad digit for implicit number-to-bool conversion");
779 			return !!i;
780 		}
781 	}
782 
783 	T readNumber(T)()
784 	{
785 		skipWhitespace();
786 		const(C)[] n;
787 		auto start = p;
788 		Unqual!C c = peek();
789 		if (c == '"') // TODO: implicit type conversion should be optional
790 			n = readSimpleString();
791 		else
792 		{
793 			while (c=='+' || c=='-' || (c>='0' && c<='9') || c=='e' || c=='E' || c=='.')
794 			{
795 				p++;
796 				if (eof) break;
797 				c = peek();
798 			}
799 			n = s[start..p];
800 		}
801 		static if (is(T : long))
802 			return to!T(n);
803 		else
804 		static if (is(T : real))
805 			return fpParse!T(n);
806 		else
807 			static assert(0, "Don't know how to parse numerical type " ~ T.stringof);
808 	}
809 
810 	T[] readArray(T)()
811 	{
812 		skipWhitespace();
813 		expect('[');
814 		skipWhitespace();
815 		T[] result;
816 		if (peek()==']')
817 		{
818 			p++;
819 			return result;
820 		}
821 		while(true)
822 		{
823 			T subvalue;
824 			read!T(subvalue);
825 			result ~= subvalue;
826 
827 			skipWhitespace();
828 			if (peek()==']')
829 			{
830 				p++;
831 				return result;
832 			}
833 			else
834 				expect(',');
835 		}
836 	}
837 
838 	void readStaticArray(T, size_t n)(ref T[n] value)
839 	{
840 		skipWhitespace();
841 		expect('[');
842 		skipWhitespace();
843 		foreach (i, ref subvalue; value)
844 		{
845 			if (i)
846 			{
847 				expect(',');
848 				skipWhitespace();
849 			}
850 			read(subvalue);
851 			skipWhitespace();
852 		}
853 		expect(']');
854 	}
855 
856 	void readObject(T)(ref T v)
857 	{
858 		skipWhitespace();
859 		expect('{');
860 		skipWhitespace();
861 		if (peek()=='}')
862 		{
863 			p++;
864 			return;
865 		}
866 
867 		while (true)
868 		{
869 			auto jsonField = readSimpleString();
870 			mixin(exceptionContext(q{"Error with field " ~ to!string(jsonField)}));
871 			skipWhitespace();
872 			expect(':');
873 
874 			bool found;
875 			foreach (i, ref field; v.tupleof)
876 			{
877 				enum name = getJsonName!(T, v.tupleof[i].stringof[2..$]);
878 				if (name == jsonField)
879 				{
880 					read(field);
881 					found = true;
882 					break;
883 				}
884 			}
885 
886 			if (!found)
887 			{
888 				static if (hasAttribute!(JSONPartial, T))
889 					skipValue();
890 				else
891 					throw new Exception(cast(string)("Unknown field " ~ jsonField));
892 			}
893 
894 			skipWhitespace();
895 			if (peek()=='}')
896 			{
897 				p++;
898 				return;
899 			}
900 			else
901 				expect(',');
902 		}
903 	}
904 
905 	void readAA(T)(ref T v)
906 	{
907 		skipWhitespace();
908 		static if (is(typeof(T.init is null)))
909 			if (peek() == 'n')
910 			{
911 				v = readNull();
912 				return;
913 			}
914 		expect('{');
915 		skipWhitespace();
916 		if (peek()=='}')
917 		{
918 			p++;
919 			return;
920 		}
921 		alias K = typeof(v.keys[0]);
922 
923 		while (true)
924 		{
925 			K jsonField;
926 			static if (is(K == string))
927 				jsonField = readString().to!K;
928 			else
929 			{
930 				static if (options.nonStringKeys == JsonOptions.NonStringKeys.asIs)
931 					read(jsonField);
932 				else
933 				static if (options.nonStringKeys == JsonOptions.NonStringKeys.stringify)
934 					jsonField = readString().jsonParse!(K, options);
935 				else
936 					static assert(false, "Cannot parse associative array with non-string key " ~ K.stringof);
937 			}
938 
939 			skipWhitespace();
940 			expect(':');
941 
942 			// TODO: elide copy
943 			typeof(v.values[0]) subvalue;
944 			read(subvalue);
945 			v[jsonField] = subvalue;
946 
947 			skipWhitespace();
948 			if (peek()=='}')
949 			{
950 				p++;
951 				return;
952 			}
953 			else
954 				expect(',');
955 		}
956 	}
957 
958 	T readEnum(T)()
959 	{
960 		return to!T(readSimpleString());
961 	}
962 
963 	T readPointer(T)()
964 	{
965 		skipWhitespace();
966 		if (peek()=='n')
967 		{
968 			enforce(readN(4) == "null", "Null expected");
969 			return null;
970 		}
971 		alias S = typeof(*T.init);
972 		T v = new S;
973 		read!S(*v);
974 		return v;
975 	}
976 
977 	void skipValue()
978 	{
979 		skipWhitespace();
980 		Unqual!C c = peek();
981 		switch (c)
982 		{
983 			case '"':
984 				readString(); // TODO: Optimize
985 				break;
986 			case '0': .. case '9':
987 			case '-':
988 				while (c=='+' || c=='-' || (c>='0' && c<='9') || c=='e' || c=='E' || c=='.')
989 				{
990 					p++;
991 					if (eof) break;
992 					c = peek();
993 				}
994 				break;
995 			case '{':
996 				next();
997 				skipWhitespace();
998 				bool first = true;
999 				while (peek() != '}')
1000 				{
1001 					if (first)
1002 						first = false;
1003 					else
1004 						expect(',');
1005 					skipValue(); // key
1006 					skipWhitespace();
1007 					expect(':');
1008 					skipValue(); // value
1009 					skipWhitespace();
1010 				}
1011 				expect('}');
1012 				break;
1013 			case '[':
1014 				next();
1015 				skipWhitespace();
1016 				bool first = true;
1017 				while (peek() != ']')
1018 				{
1019 					if (first)
1020 						first = false;
1021 					else
1022 						expect(',');
1023 					skipValue();
1024 					skipWhitespace();
1025 				}
1026 				expect(']');
1027 				break;
1028 			case 't':
1029 				foreach (l; "true")
1030 					expect(l);
1031 				break;
1032 			case 'f':
1033 				foreach (l; "false")
1034 					expect(l);
1035 				break;
1036 			case 'n':
1037 				foreach (l; "null")
1038 					expect(l);
1039 				break;
1040 			default:
1041 				throw new Exception(text("Can't parse: ", c));
1042 		}
1043 	}
1044 }
1045 
1046 /// Parse the JSON in string `s` and deserialize it into an instance of `T`.
1047 template jsonParse(T, JsonOptions options = JsonOptions.init)
1048 {
1049 	T jsonParse(C)(C[] s)
1050 	{
1051 		auto parser = JsonParser!(C, options)(s);
1052 		mixin(exceptionContext(q{format("Error at position %d", parser.p)}));
1053 		T result;
1054 		parser.read!T(result);
1055 		return result;
1056 	}
1057 }
1058 
1059 debug(ae_unittest) unittest
1060 {
1061 	struct S { int i; S[] arr; S* p0, p1; }
1062 	S s = S(42, [S(1), S(2)], null, new S(15));
1063 	auto s2 = jsonParse!S(toJson(s));
1064 	//assert(s == s2); // Issue 3789
1065 	assert(s.i == s2.i && s.arr == s2.arr && s.p0 is s2.p0 && *s.p1 == *s2.p1);
1066 	jsonParse!S(toJson(s).dup);
1067 
1068 	assert(jsonParse!(Tuple!())(``) == tuple());
1069 	assert(jsonParse!(Tuple!int)(`42`) == tuple(42));
1070 	assert(jsonParse!(Tuple!(int, string))(`[42, "banana"]`) == tuple(42, "banana"));
1071 
1072 	assert(jsonParse!(string[string])(`null`) is null);
1073 }
1074 
1075 debug(ae_unittest) unittest
1076 {
1077 	struct T { string s; wstring w; dstring d; }
1078 	T t;
1079 	auto s = t.toJson;
1080 	assert(s == `{"s":null,"w":null,"d":null}`, s);
1081 
1082 	t.s = "foo";
1083 	t.w = "bar"w;
1084 	t.d = "baz"d;
1085 	s = t.toJson;
1086 	assert(s == `{"s":"foo","w":"bar","d":"baz"}`, s);
1087 
1088 	jsonParse!T(s);
1089 	jsonParse!T(cast(char[]) s);
1090 	jsonParse!T(cast(const(char)[]) s);
1091 	jsonParse!T(s.to!wstring);
1092 	jsonParse!T(s.to!dstring);
1093 }
1094 
1095 debug(ae_unittest) unittest
1096 {
1097 	jsonParse!(int[2])(`[ 1 , 2 ]`);
1098 }
1099 
1100 // NaNs and infinities are serialized as strings.
1101 debug(ae_unittest) unittest
1102 {
1103 	void check(double f, string s)
1104 	{
1105 		assert(f.toJson() == s);
1106 		assert(s.jsonParse!double is f);
1107 	}
1108 	check(double.init, `"nan"`);
1109 	check(double.infinity, `"inf"`);
1110 	check(-double.infinity, `"-inf"`);
1111 }
1112 
1113 /// Parse the JSON in string `s` and deserialize it into `T`.
1114 void jsonParse(T, C)(C[] s, ref T result)
1115 {
1116 	auto parser = JsonParser!C(s);
1117 	mixin(exceptionContext(q{format("Error at position %d", parser.p)}));
1118 	parser.read!T(result);
1119 }
1120 
1121 debug(ae_unittest) unittest
1122 {
1123 	struct S { int a, b; }
1124 	S s;
1125 	s.a = 1;
1126 	jsonParse(`{"b":2}`, s);
1127 	assert(s == S(1, 2));
1128 }
1129 
1130 // ************************************************************************
1131 
1132 // TODO: migrate to UDAs
1133 
1134 /**
1135  * A template that designates fields which should not be serialized to Json.
1136  *
1137  * Example:
1138  * ---
1139  * struct Point { int x, y, z; mixin NonSerialized!(x, z); }
1140  * assert(jsonParse!Point(toJson(Point(1, 2, 3))) == Point(0, 2, 0));
1141  * ---
1142  */
1143 template NonSerialized(fields...)
1144 {
1145 	import ae.utils.meta : stringofArray;
1146 	mixin(mixNonSerializedFields(stringofArray!fields()));
1147 }
1148 
1149 private string mixNonSerializedFields(string[] fields)
1150 {
1151 	string result;
1152 	foreach (field; fields)
1153 		result ~= "enum bool " ~ field ~ "_nonSerialized = 1;";
1154 	return result;
1155 }
1156 
1157 private template doSkipSerialize(T, string member)
1158 {
1159 	enum bool doSkipSerialize = __traits(hasMember, T, member ~ "_nonSerialized");
1160 }
1161 
1162 debug(ae_unittest) unittest
1163 {
1164 	struct Point { int x, y, z; mixin NonSerialized!(x, z); }
1165 	assert(jsonParse!Point(toJson(Point(1, 2, 3))) == Point(0, 2, 0));
1166 }
1167 
1168 debug(ae_unittest) unittest
1169 {
1170 	enum En { one, two }
1171 	assert(En.one.toJson() == `"one"`);
1172 	struct S { int i1, i2; S[] arr1, arr2; string[string] dic; En en; mixin NonSerialized!(i2, arr2); }
1173 	S s = S(42, 5, [S(1), S(2)], [S(3), S(4)], ["apple":"fruit", "pizza":"vegetable"], En.two);
1174 	auto s2 = jsonParse!S(toJson(s));
1175 	assert(s.i1 == s2.i1);
1176 	assert(s2.i2 is int.init);
1177 	assert(s.arr1 == s2.arr1);
1178 	assert(s2.arr2 is null);
1179 	assert(s.dic == s2.dic, s2.dic.text);
1180 	assert(s.en == En.two);
1181 }
1182 
1183 debug(ae_unittest) unittest
1184 {
1185 	alias B = Nullable!bool;
1186 	B b;
1187 
1188 	b = jsonParse!B("true");
1189 	assert(!b.isNull);
1190 	assert(b.get == true);
1191 	assert(b.toJson == "true");
1192 
1193 	b = jsonParse!B("false");
1194 	assert(!b.isNull);
1195 	assert(b.get == false);
1196 	assert(b.toJson == "false");
1197 
1198 	b = jsonParse!B("null");
1199 	assert(b.isNull);
1200 	assert(b.toJson == "null");
1201 
1202 	struct S {}
1203 	alias NS = Nullable!S;
1204 	assert(NS.init.toJson == "null");
1205 }
1206 
1207 debug(ae_unittest) unittest // Issue 49
1208 {
1209 	immutable bool b;
1210 	assert(toJson(b) == "false");
1211 }
1212 
1213 debug(ae_unittest) unittest
1214 {
1215 	import ae.utils.aa : OrderedMap;
1216 	alias M = OrderedMap!(string, int);
1217 	M m;
1218 	m["one"] = 1;
1219 	m["two"] = 2;
1220 	auto j = (cast(const)m).toJson();
1221 	assert(j == `{"one":1,"two":2}`, j);
1222 	assert(j.jsonParse!M == m);
1223 }
1224 
1225 debug(ae_unittest) unittest
1226 {
1227 	assert(string.init.toJson.jsonParse!string  is null);
1228 	assert(""         .toJson.jsonParse!string !is null);
1229 }
1230 
1231 debug(ae_unittest) unittest
1232 {
1233 	char[] s = "{}".dup;
1234 	assert(s.jsonParse!(string[string]) == null);
1235 }
1236 
1237 debug(ae_unittest) unittest
1238 {
1239 	typeof(null) n;
1240 	assert(n.toJson.jsonParse!(typeof(null)) is null);
1241 }
1242 
1243 debug(ae_unittest) unittest
1244 {
1245 	double f = 1.5;
1246 	assert(f.toJson() == "1.5");
1247 }
1248 
1249 debug(ae_unittest) unittest
1250 {
1251 	dchar c = '😸';
1252 	assert(c.toJson() == `"😸"`);
1253 }
1254 
1255 /// `fromJSON` / `toJSON` can be added to a type to control their serialized representation.
1256 debug(ae_unittest) unittest
1257 {
1258 	static struct S
1259 	{
1260 		string value;
1261 		static S fromJSON(string value) { return S(value); }
1262 		string toJSON() { return value; }
1263 	}
1264 	auto s = S("test");
1265 	assert(s.toJson == `"test"`);
1266 	assert(s.toJson.jsonParse!S == s);
1267 }
1268 
1269 debug(ae_unittest) unittest
1270 {
1271 	static struct S
1272 	{
1273 		string value;
1274 		static S fromJSON(string value) { return S(value); }
1275 		void toJSON(F)(F f) { f(value); }
1276 	}
1277 	auto s = S("test");
1278 	auto p = &s;
1279 	assert(p.toJson == `"test"`);
1280 	assert(*p.toJson.jsonParse!(S*) == s);
1281 }
1282 
1283 /// `fromJSON` / `toJSON` can also accept/return a `JSONFragment`,
1284 /// which allows full control over JSON serialization.
1285 debug(ae_unittest) unittest
1286 {
1287 	static struct BigInt
1288 	{
1289 		string decimalDigits;
1290 		static BigInt fromJSON(JSONFragment value) { return BigInt(value.json); }
1291 		JSONFragment toJSON() { return JSONFragment(decimalDigits); }
1292 	}
1293 	auto n = BigInt("12345678901234567890");
1294 	assert(n.toJson == `12345678901234567890`);
1295 	assert(n.toJson.jsonParse!BigInt == n);
1296 }
1297 
1298 // ************************************************************************
1299 
1300 /// User-defined attribute - specify name for JSON object field.
1301 /// Useful when a JSON object may contain fields, the name of which are not valid D identifiers.
1302 struct JSONName { string name; /***/ }
1303 
1304 private template getJsonName(S, string FIELD)
1305 {
1306 	static if (hasAttribute!(JSONName, __traits(getMember, S, FIELD)))
1307 		enum getJsonName = getAttribute!(JSONName, __traits(getMember, S, FIELD)).name;
1308 	else
1309 		enum getJsonName = FIELD;
1310 }
1311 
1312 // ************************************************************************
1313 
1314 /// User-defined attribute - only serialize this field if its value is different from its .init value.
1315 struct JSONOptional {}
1316 
1317 debug(ae_unittest) unittest
1318 {
1319 	static struct S { @JSONOptional bool a=true, b=false; }
1320 	assert(S().toJson == `{}`, S().toJson);
1321 	assert(S(false, true).toJson == `{"a":false,"b":true}`);
1322 }
1323 
1324 debug(ae_unittest) unittest
1325 {
1326 	static struct S { @JSONOptional float f; }
1327 	assert(S().toJson == `{}`, S().toJson);
1328 }
1329 
1330 debug(ae_unittest) unittest
1331 {
1332 	static struct S { @JSONOptional int[1] a; }
1333 	assert(S().toJson == `{}`, S().toJson);
1334 }
1335 
1336 // ************************************************************************
1337 
1338 /// User-defined attribute - skip unknown fields when deserializing.
1339 struct JSONPartial {}
1340 
1341 debug(ae_unittest) unittest
1342 {
1343 	@JSONPartial static struct S { int b; }
1344 	assert(`{"a":1,"b":2,"c":3.4,"d":[5,"x"],"de":[],"e":{"k":"v"},"ee":{},"f":true,"g":false,"h":null}`.jsonParse!S == S(2));
1345 }
1346 
1347 // ************************************************************************
1348 
1349 /// Fragment of raw JSON.
1350 /// When serialized, the .json field is inserted into the resulting
1351 /// string verbatim, without any validation.
1352 /// When deserialized, will contain the raw JSON of one JSON object of
1353 /// any type.
1354 struct JSONFragment
1355 {
1356 	string json; ///
1357 	bool opCast(T)() const if (is(T==bool)) { return !!json; } ///
1358 }
1359 
1360 debug(ae_unittest) unittest
1361 {
1362 	JSONFragment[] arr = [JSONFragment(`1`), JSONFragment(`true`), JSONFragment(`"foo"`), JSONFragment(`[55]`)];
1363 	assert(arr.toJson == `[1,true,"foo",[55]]`);
1364 	assert(arr.toJson.jsonParse!(JSONFragment[]) == arr);
1365 }
1366 
1367 // ************************************************************************
1368 
1369 debug(ae_unittest) unittest
1370 {
1371 	int[int] aa = [3: 4];
1372 	{
1373 		enum JsonOptions options = { nonStringKeys: JsonOptions.NonStringKeys.error };
1374 		static assert(!__traits(compiles, aa.toJson!options));
1375 		static assert(!__traits(compiles, "".jsonParse!(typeof(aa), options)));
1376 	}
1377 	{
1378 		enum JsonOptions options = { nonStringKeys: JsonOptions.NonStringKeys.asIs };
1379 		auto s = aa.toJson!options;
1380 		assert(s == `{3:4}`);
1381 		assert(s.jsonParse!(typeof(aa), options) == aa);
1382 	}
1383 	{
1384 		enum JsonOptions options = { nonStringKeys: JsonOptions.NonStringKeys.stringify };
1385 		auto s = aa.toJson!options;
1386 		assert(s == `{"3":4}`);
1387 		assert(s.jsonParse!(typeof(aa), options) == aa);
1388 	}
1389 }