Okay, I found your real bug.
procedure WriteString(AStream: TStream; AValue: JSON_String);
// snip
var
i,j: integer;
s: string;
begin
WriteChar(AStream, '"');
for i := _StrLow to _StrHigh(AValue) do begin
case ord(AValue[i]) of
22 {"} : WriteTag('"');
92 {\} : WriteTag('\');
Okay, this is the wrong part. The 22 is the HEX version of the double-quote, and the Ordinal Decimal should be 34. So what is happening is that the code is converting the wrong character. I presume that the read is then wrong too. But fixing the read is breaking the rest of the code.