namespace System.Runtime.Serialization.Json
{
- internal class JavaScriptReader
- {
- private readonly TextReader _r;
- private int _line = 1, _column = 0;
+ internal class JavaScriptReader
+ {
+ private readonly TextReader _r;
+ private int _line = 1, _column = 0;
- public JavaScriptReader (TextReader reader, bool raiseOnNumberError)
- {
- if (reader == null)
- throw new ArgumentNullException (nameof(reader));
- this._r = reader;
- }
+ public JavaScriptReader(TextReader reader, bool raiseOnNumberError)
+ {
+ if (reader == null)
+ throw new ArgumentNullException(nameof(reader));
+ _r = reader;
+ }
- public object Read ()
- {
- object v = ReadCore ();
- SkipSpaces ();
- if (ReadChar () >= 0)
- throw JsonError (string.Format ("extra characters in JSON input"));
- return v;
- }
+ public object Read()
+ {
+ object v = ReadCore();
+ SkipSpaces();
+ if (ReadChar() >= 0)
+ throw JsonError(string.Format("extra characters in JSON input"));
+ return v;
+ }
- object ReadCore ()
- {
- SkipSpaces ();
- int c = PeekChar ();
- if (c < 0)
- throw JsonError ("Incomplete JSON input");
- switch (c) {
- case '[':
- ReadChar ();
- var list = new List<object> ();
- SkipSpaces ();
- if (PeekChar () == ']') {
- ReadChar ();
- return list;
- }
- while (true) {
- list.Add (ReadCore ());
- SkipSpaces ();
- c = PeekChar ();
- if (c != ',')
- break;
- ReadChar ();
- continue;
- }
- if (ReadChar () != ']')
- throw JsonError ("JSON array must end with ']'");
- return list.ToArray ();
- case '{':
- ReadChar ();
- var obj = new Dictionary<string,object> ();
- SkipSpaces ();
- if (PeekChar () == '}') {
- ReadChar ();
- return obj;
- }
- while (true) {
- SkipSpaces ();
- if (PeekChar () == '}') {
- ReadChar ();
- break;
- }
- string name = ReadStringLiteral ();
- SkipSpaces ();
- Expect (':');
- SkipSpaces ();
- obj [name] = ReadCore (); // it does not reject duplicate names.
- SkipSpaces ();
- c = ReadChar ();
- if (c == ',')
- continue;
- if (c == '}')
- break;
- }
- return obj.ToArray ();
- case 't':
- Expect ("true");
- return true;
- case 'f':
- Expect ("false");
- return false;
- case 'n':
- Expect ("null");
- // FIXME: what should we return?
- return (string) null;
- case '"':
- return ReadStringLiteral ();
- default:
- if ('0' <= c && c <= '9' || c == '-')
- return ReadNumericLiteral ();
- else
- throw JsonError (string.Format ("Unexpected character '{0}'", (char) c));
- }
- }
+ private object ReadCore()
+ {
+ SkipSpaces();
+ int c = PeekChar();
+ if (c < 0)
+ throw JsonError("Incomplete JSON input");
+ switch (c)
+ {
+ case '[':
+ ReadChar();
+ var list = new List<object>();
+ SkipSpaces();
+ if (PeekChar() == ']')
+ {
+ ReadChar();
+ return list;
+ }
+ while (true)
+ {
+ list.Add(ReadCore());
+ SkipSpaces();
+ c = PeekChar();
+ if (c != ',')
+ break;
+ ReadChar();
+ continue;
+ }
+ if (ReadChar() != ']')
+ throw JsonError("JSON array must end with ']'");
+ return list.ToArray();
+ case '{':
+ ReadChar();
+ var obj = new Dictionary<string, object>();
+ SkipSpaces();
+ if (PeekChar() == '}')
+ {
+ ReadChar();
+ return obj;
+ }
+ while (true)
+ {
+ SkipSpaces();
+ if (PeekChar() == '}')
+ {
+ ReadChar();
+ break;
+ }
+ string name = ReadStringLiteral();
+ SkipSpaces();
+ Expect(':');
+ SkipSpaces();
+ obj[name] = ReadCore(); // it does not reject duplicate names.
+ SkipSpaces();
+ c = ReadChar();
+ if (c == ',')
+ continue;
+ if (c == '}')
+ break;
+ }
+ return obj.ToArray();
+ case 't':
+ Expect("true");
+ return true;
+ case 'f':
+ Expect("false");
+ return false;
+ case 'n':
+ Expect("null");
+ // FIXME: what should we return?
+ return (string)null;
+ case '"':
+ return ReadStringLiteral();
+ default:
+ if ('0' <= c && c <= '9' || c == '-')
+ return ReadNumericLiteral();
+ else
+ throw JsonError(string.Format("Unexpected character '{0}'", (char)c));
+ }
+ }
- int peek;
- bool has_peek;
- bool prev_lf;
+ private int _peek;
+ private bool _has_peek;
+ private bool _prev_lf;
- int PeekChar ()
- {
- if (!has_peek) {
- peek = _r.Read ();
- has_peek = true;
- }
- return peek;
- }
+ private int PeekChar()
+ {
+ if (!_has_peek)
+ {
+ _peek = _r.Read();
+ _has_peek = true;
+ }
+ return _peek;
+ }
- int ReadChar ()
- {
- int v = has_peek ? peek : _r.Read ();
+ private int ReadChar()
+ {
+ int v = _has_peek ? _peek : _r.Read();
- has_peek = false;
+ _has_peek = false;
- if (prev_lf) {
- _line++;
- _column = 0;
- prev_lf = false;
- }
+ if (_prev_lf)
+ {
+ _line++;
+ _column = 0;
+ _prev_lf = false;
+ }
- if (v == '\n')
- prev_lf = true;
- _column++;
+ if (v == '\n')
+ _prev_lf = true;
+ _column++;
- return v;
- }
+ return v;
+ }
- void SkipSpaces ()
- {
- while (true) {
- switch (PeekChar ()) {
- case ' ': case '\t': case '\r': case '\n':
- ReadChar ();
- continue;
- default:
- return;
- }
- }
- }
+ private void SkipSpaces()
+ {
+ while (true)
+ {
+ switch (PeekChar())
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ ReadChar();
+ continue;
+ default:
+ return;
+ }
+ }
+ }
- // It could return either int, long or decimal, depending on the parsed value.
- object ReadNumericLiteral ()
- {
- var sb = new StringBuilder ();
-
- if (PeekChar () == '-') {
- sb.Append ((char) ReadChar ());
- }
+ // It could return either int, long or decimal, depending on the parsed value.
+ private object ReadNumericLiteral()
+ {
+ var sb = new StringBuilder();
- int c;
- int x = 0;
- bool zeroStart = PeekChar () == '0';
- for (; ; x++) {
- c = PeekChar ();
- if (c < '0' || '9' < c)
- break;
- sb.Append ((char) ReadChar ());
- if (zeroStart && x == 1)
- throw JsonError ("leading zeros are not allowed");
- }
- if (x == 0) // Reached e.g. for "- "
- throw JsonError ("Invalid JSON numeric literal; no digit found");
+ if (PeekChar() == '-')
+ {
+ sb.Append((char)ReadChar());
+ }
- // fraction
- bool hasFrac = false;
- int fdigits = 0;
- if (PeekChar () == '.') {
- hasFrac = true;
- sb.Append ((char) ReadChar ());
- if (PeekChar () < 0)
- throw JsonError ("Invalid JSON numeric literal; extra dot");
- while (true) {
- c = PeekChar ();
- if (c < '0' || '9' < c)
- break;
- sb.Append ((char) ReadChar ());
- fdigits++;
- }
- if (fdigits == 0)
- throw JsonError ("Invalid JSON numeric literal; extra dot");
- }
+ int c;
+ int x = 0;
+ bool zeroStart = PeekChar() == '0';
+ for (; ; x++)
+ {
+ c = PeekChar();
+ if (c < '0' || '9' < c)
+ break;
+ sb.Append((char)ReadChar());
+ if (zeroStart && x == 1)
+ throw JsonError("leading zeros are not allowed");
+ }
+ if (x == 0) // Reached e.g. for "- "
+ throw JsonError("Invalid JSON numeric literal; no digit found");
- c = PeekChar ();
- if (c != 'e' && c != 'E') {
- if (!hasFrac) {
- int valueInt;
- if (int.TryParse (sb.ToString (), NumberStyles.Float, CultureInfo.InvariantCulture, out valueInt))
- return valueInt;
-
- long valueLong;
- if (long.TryParse (sb.ToString (), NumberStyles.Float, CultureInfo.InvariantCulture, out valueLong))
- return valueLong;
-
- ulong valueUlong;
- if (ulong.TryParse (sb.ToString (), NumberStyles.Float, CultureInfo.InvariantCulture, out valueUlong))
- return valueUlong;
- }
- decimal valueDecimal;
- if (decimal.TryParse (sb.ToString (), NumberStyles.Float, CultureInfo.InvariantCulture, out valueDecimal) && valueDecimal != 0)
- return valueDecimal;
- } else {
- // exponent
- sb.Append ((char) ReadChar ());
- if (PeekChar () < 0)
- throw new ArgumentException ("Invalid JSON numeric literal; incomplete exponent");
-
- c = PeekChar ();
- if (c == '-') {
- sb.Append ((char) ReadChar ());
- }
- else if (c == '+')
- sb.Append ((char) ReadChar ());
+ // fraction
+ bool hasFrac = false;
+ int fdigits = 0;
+ if (PeekChar() == '.')
+ {
+ hasFrac = true;
+ sb.Append((char)ReadChar());
+ if (PeekChar() < 0)
+ throw JsonError("Invalid JSON numeric literal; extra dot");
+ while (true)
+ {
+ c = PeekChar();
+ if (c < '0' || '9' < c)
+ break;
+ sb.Append((char)ReadChar());
+ fdigits++;
+ }
+ if (fdigits == 0)
+ throw JsonError("Invalid JSON numeric literal; extra dot");
+ }
- if (PeekChar () < 0)
- throw JsonError ("Invalid JSON numeric literal; incomplete exponent");
- while (true) {
- c = PeekChar ();
- if (c < '0' || '9' < c)
- break;
- sb.Append ((char) ReadChar ());
- }
- }
+ c = PeekChar();
+ if (c != 'e' && c != 'E')
+ {
+ if (!hasFrac)
+ {
+ int valueInt;
+ if (int.TryParse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out valueInt))
+ return valueInt;
- return double.Parse (sb.ToString (), NumberStyles.Float, CultureInfo.InvariantCulture);
- }
+ long valueLong;
+ if (long.TryParse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out valueLong))
+ return valueLong;
- private readonly StringBuilder _vb = new StringBuilder ();
+ ulong valueUlong;
+ if (ulong.TryParse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out valueUlong))
+ return valueUlong;
+ }
+ decimal valueDecimal;
+ if (decimal.TryParse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out valueDecimal) && valueDecimal != 0)
+ return valueDecimal;
+ }
+ else
+ {
+ // exponent
+ sb.Append((char)ReadChar());
+ if (PeekChar() < 0)
+ throw new ArgumentException("Invalid JSON numeric literal; incomplete exponent");
- private string ReadStringLiteral ()
- {
- if (PeekChar () != '"')
- throw JsonError ("Invalid JSON string literal format");
+ c = PeekChar();
+ if (c == '-')
+ {
+ sb.Append((char)ReadChar());
+ }
+ else if (c == '+')
+ sb.Append((char)ReadChar());
- ReadChar ();
- _vb.Length = 0;
- while (true) {
- int c = ReadChar ();
- if (c < 0)
- throw JsonError ("JSON string is not closed");
- if (c == '"')
- return _vb.ToString ();
- else if (c != '\\') {
- _vb.Append ((char) c);
- continue;
- }
+ if (PeekChar() < 0)
+ throw JsonError("Invalid JSON numeric literal; incomplete exponent");
+ while (true)
+ {
+ c = PeekChar();
+ if (c < '0' || '9' < c)
+ break;
+ sb.Append((char)ReadChar());
+ }
+ }
- // escaped expression
- c = ReadChar ();
- if (c < 0)
- throw JsonError ("Invalid JSON string literal; incomplete escape sequence");
- switch (c) {
- case '"':
- case '\\':
- case '/':
- _vb.Append ((char) c);
- break;
- case 'b':
- _vb.Append ('\x8');
- break;
- case 'f':
- _vb.Append ('\f');
- break;
- case 'n':
- _vb.Append ('\n');
- break;
- case 'r':
- _vb.Append ('\r');
- break;
- case 't':
- _vb.Append ('\t');
- break;
- case 'u':
- ushort cp = 0;
- for (int i = 0; i < 4; i++) {
- cp <<= 4;
- if ((c = ReadChar ()) < 0)
- throw JsonError ("Incomplete unicode character escape literal");
- if ('0' <= c && c <= '9')
- cp += (ushort) (c - '0');
- if ('A' <= c && c <= 'F')
- cp += (ushort) (c - 'A' + 10);
- if ('a' <= c && c <= 'f')
- cp += (ushort) (c - 'a' + 10);
- }
- _vb.Append ((char) cp);
- break;
- default:
- throw JsonError ("Invalid JSON string literal; unexpected escape character");
- }
- }
- }
+ return double.Parse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture);
+ }
- private void Expect (char expected)
- {
- int c;
- if ((c = ReadChar ()) != expected)
- throw JsonError (string.Format ("Expected '{0}', got '{1}'", expected, (char) c));
- }
+ private readonly StringBuilder _vb = new StringBuilder();
- private void Expect (string expected)
- {
- for (int i = 0; i < expected.Length; i++)
- if (ReadChar () != expected [i])
- throw JsonError (string.Format ("Expected '{0}', differed at {1}", expected, i));
- }
+ private string ReadStringLiteral()
+ {
+ if (PeekChar() != '"')
+ throw JsonError("Invalid JSON string literal format");
- private Exception JsonError (string msg)
- {
- return new ArgumentException (string.Format ("{0}. At line {1}, column {2}", msg, _line, _column));
- }
- }
+ ReadChar();
+ _vb.Length = 0;
+ while (true)
+ {
+ int c = ReadChar();
+ if (c < 0)
+ throw JsonError("JSON string is not closed");
+ if (c == '"')
+ return _vb.ToString();
+ else if (c != '\\')
+ {
+ _vb.Append((char)c);
+ continue;
+ }
+
+ // escaped expression
+ c = ReadChar();
+ if (c < 0)
+ throw JsonError("Invalid JSON string literal; incomplete escape sequence");
+ switch (c)
+ {
+ case '"':
+ case '\\':
+ case '/':
+ _vb.Append((char)c);
+ break;
+ case 'b':
+ _vb.Append('\x8');
+ break;
+ case 'f':
+ _vb.Append('\f');
+ break;
+ case 'n':
+ _vb.Append('\n');
+ break;
+ case 'r':
+ _vb.Append('\r');
+ break;
+ case 't':
+ _vb.Append('\t');
+ break;
+ case 'u':
+ ushort cp = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ cp <<= 4;
+ if ((c = ReadChar()) < 0)
+ throw JsonError("Incomplete unicode character escape literal");
+ if ('0' <= c && c <= '9')
+ cp += (ushort)(c - '0');
+ if ('A' <= c && c <= 'F')
+ cp += (ushort)(c - 'A' + 10);
+ if ('a' <= c && c <= 'f')
+ cp += (ushort)(c - 'a' + 10);
+ }
+ _vb.Append((char)cp);
+ break;
+ default:
+ throw JsonError("Invalid JSON string literal; unexpected escape character");
+ }
+ }
+ }
+
+ private void Expect(char expected)
+ {
+ int c;
+ if ((c = ReadChar()) != expected)
+ throw JsonError(string.Format("Expected '{0}', got '{1}'", expected, (char)c));
+ }
+
+ private void Expect(string expected)
+ {
+ for (int i = 0; i < expected.Length; i++)
+ if (ReadChar() != expected[i])
+ throw JsonError(string.Format("Expected '{0}', differed at {1}", expected, i));
+ }
+
+ private Exception JsonError(string msg)
+ {
+ return new ArgumentException(string.Format("{0}. At line {1}, column {2}", msg, _line, _column));
+ }
+ }
}
namespace System.Json
{
- public class JsonArray : JsonValue, IList<JsonValue>
- {
- private readonly List<JsonValue> _list;
-
- public JsonArray (params JsonValue [] items)
- {
- _list = new List<JsonValue> ();
- AddRange (items);
- }
-
- public JsonArray (IEnumerable<JsonValue> items)
- {
- if (items == null)
- throw new ArgumentNullException (nameof(items));
-
- _list = new List<JsonValue> (items);
- }
-
- public override int Count {
- get { return _list.Count; }
- }
-
- public bool IsReadOnly {
- get { return false; }
- }
-
- public override sealed JsonValue this [int index] {
- get { return _list [index]; }
- set { _list [index] = value; }
- }
-
- public override JsonType JsonType {
- get { return JsonType.Array; }
- }
-
- public void Add (JsonValue item)
- {
- if (item == null)
- throw new ArgumentNullException (nameof(item));
-
- _list.Add (item);
- }
-
- public void AddRange (IEnumerable<JsonValue> items)
- {
+ public class JsonArray : JsonValue, IList<JsonValue>
+ {
+ private readonly List<JsonValue> _list;
+
+ public JsonArray(params JsonValue[] items)
+ {
+ _list = new List<JsonValue>();
+ AddRange(items);
+ }
+
+ public JsonArray(IEnumerable<JsonValue> items)
+ {
if (items == null)
throw new ArgumentNullException(nameof(items));
- _list.AddRange (items);
- }
-
- public void AddRange (params JsonValue [] items)
- {
- if (items == null)
- return;
-
- _list.AddRange (items);
- }
-
- public void Clear ()
- {
- _list.Clear ();
- }
-
- public bool Contains (JsonValue item)
- {
- return _list.Contains (item);
- }
-
- public void CopyTo (JsonValue [] array, int arrayIndex)
- {
- _list.CopyTo (array, arrayIndex);
- }
-
- public int IndexOf (JsonValue item)
- {
- return _list.IndexOf (item);
- }
-
- public void Insert (int index, JsonValue item)
- {
- _list.Insert (index, item);
- }
-
- public bool Remove (JsonValue item)
- {
- return _list.Remove (item);
- }
-
- public void RemoveAt (int index)
- {
- _list.RemoveAt (index);
- }
-
- public override void Save (Stream stream)
- {
+ _list = new List<JsonValue>(items);
+ }
+
+ public override int Count
+ {
+ get { return _list.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public override sealed JsonValue this[int index]
+ {
+ get { return _list[index]; }
+ set { _list[index] = value; }
+ }
+
+ public override JsonType JsonType
+ {
+ get { return JsonType.Array; }
+ }
+
+ public void Add(JsonValue item)
+ {
+ if (item == null)
+ throw new ArgumentNullException(nameof(item));
+
+ _list.Add(item);
+ }
+
+ public void AddRange(IEnumerable<JsonValue> items)
+ {
+ if (items == null)
+ throw new ArgumentNullException(nameof(items));
+
+ _list.AddRange(items);
+ }
+
+ public void AddRange(params JsonValue[] items)
+ {
+ if (items == null)
+ return;
+
+ _list.AddRange(items);
+ }
+
+ public void Clear()
+ {
+ _list.Clear();
+ }
+
+ public bool Contains(JsonValue item)
+ {
+ return _list.Contains(item);
+ }
+
+ public void CopyTo(JsonValue[] array, int arrayIndex)
+ {
+ _list.CopyTo(array, arrayIndex);
+ }
+
+ public int IndexOf(JsonValue item)
+ {
+ return _list.IndexOf(item);
+ }
+
+ public void Insert(int index, JsonValue item)
+ {
+ _list.Insert(index, item);
+ }
+
+ public bool Remove(JsonValue item)
+ {
+ return _list.Remove(item);
+ }
+
+ public void RemoveAt(int index)
+ {
+ _list.RemoveAt(index);
+ }
+
+ public override void Save(Stream stream)
+ {
if (stream == null)
throw new ArgumentNullException(nameof(stream));
- stream.WriteByte ((byte) '[');
- for (int i = 0; i < _list.Count; i++) {
- JsonValue v = _list [i];
- if (v != null)
- v.Save (stream);
- else {
- stream.WriteByte ((byte) 'n');
- stream.WriteByte ((byte) 'u');
- stream.WriteByte ((byte) 'l');
- stream.WriteByte ((byte) 'l');
- }
-
- if (i < Count - 1) {
- stream.WriteByte ((byte) ',');
- stream.WriteByte ((byte) ' ');
- }
- }
- stream.WriteByte ((byte) ']');
- }
-
- IEnumerator<JsonValue> IEnumerable<JsonValue>.GetEnumerator ()
- {
- return _list.GetEnumerator ();
- }
-
- IEnumerator IEnumerable.GetEnumerator ()
- {
- return _list.GetEnumerator ();
- }
- }
+ stream.WriteByte((byte)'[');
+ for (int i = 0; i < _list.Count; i++)
+ {
+ JsonValue v = _list[i];
+ if (v != null)
+ v.Save(stream);
+ else
+ {
+ stream.WriteByte((byte)'n');
+ stream.WriteByte((byte)'u');
+ stream.WriteByte((byte)'l');
+ stream.WriteByte((byte)'l');
+ }
+
+ if (i < Count - 1)
+ {
+ stream.WriteByte((byte)',');
+ stream.WriteByte((byte)' ');
+ }
+ }
+ stream.WriteByte((byte)']');
+ }
+
+ IEnumerator<JsonValue> IEnumerable<JsonValue>.GetEnumerator()
+ {
+ return _list.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _list.GetEnumerator();
+ }
+ }
}
namespace System.Json
{
public class JsonObject : JsonValue, IDictionary<string, JsonValue>, ICollection<JsonPair>
- {
- // Use SortedDictionary to make result of ToString() deterministic
- SortedDictionary<string, JsonValue> map;
+ {
+ // Use SortedDictionary to make result of ToString() deterministic
+ private SortedDictionary<string, JsonValue> _map;
- public JsonObject (params JsonPair [] items)
- {
- map = new SortedDictionary<string, JsonValue> (StringComparer.Ordinal);
+ public JsonObject(params JsonPair[] items)
+ {
+ _map = new SortedDictionary<string, JsonValue>(StringComparer.Ordinal);
- if (items != null)
- AddRange (items);
- }
+ if (items != null)
+ AddRange(items);
+ }
- public JsonObject (JsonPairEnumerable items)
- {
+ public JsonObject(JsonPairEnumerable items)
+ {
if (items == null)
throw new ArgumentNullException(nameof(items));
- map = new SortedDictionary<string, JsonValue> (StringComparer.Ordinal);
- AddRange (items);
- }
-
- public override int Count {
- get { return map.Count; }
- }
-
- public IEnumerator<JsonPair> GetEnumerator ()
- {
- return map.GetEnumerator ();
- }
-
- IEnumerator IEnumerable.GetEnumerator ()
- {
- return map.GetEnumerator ();
- }
-
- public override sealed JsonValue this [string key] {
- get { return map [key]; }
- set { map [key] = value; }
- }
-
- public override JsonType JsonType {
- get { return JsonType.Object; }
- }
-
- public ICollection<string> Keys {
- get { return map.Keys; }
- }
-
- public ICollection<JsonValue> Values {
- get { return map.Values; }
- }
-
- public void Add (string key, JsonValue value)
- {
- if (key == null)
- throw new ArgumentNullException ("key");
-
- map.Add (key, value);
- }
-
- public void Add (JsonPair pair)
- {
- Add (pair.Key, pair.Value);
- }
-
- public void AddRange (JsonPairEnumerable items)
- {
- if (items == null)
- throw new ArgumentNullException ("items");
-
- foreach (var pair in items)
- map.Add (pair.Key, pair.Value);
- }
-
- public void AddRange (params JsonPair [] items)
- {
- AddRange ((JsonPairEnumerable) items);
- }
-
- public void Clear ()
- {
- map.Clear ();
- }
-
- bool ICollection<JsonPair>.Contains (JsonPair item)
- {
- return (map as ICollection<JsonPair>).Contains (item);
- }
-
- bool ICollection<JsonPair>.Remove (JsonPair item)
- {
- return (map as ICollection<JsonPair>).Remove (item);
- }
-
- public override bool ContainsKey (string key)
- {
- if (key == null)
- throw new ArgumentNullException ("key");
-
- return map.ContainsKey (key);
- }
-
- public void CopyTo (JsonPair [] array, int arrayIndex)
- {
- (map as ICollection<JsonPair>).CopyTo (array, arrayIndex);
- }
-
- public bool Remove (string key)
- {
- if (key == null)
- throw new ArgumentNullException ("key");
-
- return map.Remove (key);
- }
-
- bool ICollection<JsonPair>.IsReadOnly {
- get { return false; }
- }
-
- public override void Save (Stream stream)
- {
- if (stream == null)
- throw new ArgumentNullException ("stream");
- stream.WriteByte ((byte) '{');
- foreach (JsonPair pair in map) {
- stream.WriteByte ((byte) '"');
- byte [] bytes = Encoding.UTF8.GetBytes (EscapeString (pair.Key));
- stream.Write (bytes, 0, bytes.Length);
- stream.WriteByte ((byte) '"');
- stream.WriteByte ((byte) ',');
- stream.WriteByte ((byte) ' ');
- if (pair.Value == null) {
- stream.WriteByte ((byte) 'n');
- stream.WriteByte ((byte) 'u');
- stream.WriteByte ((byte) 'l');
- stream.WriteByte ((byte) 'l');
- } else
- pair.Value.Save (stream);
- }
- stream.WriteByte ((byte) '}');
- }
-
- public bool TryGetValue (string key, out JsonValue value)
- {
- return map.TryGetValue (key, out value);
- }
- }
+ _map = new SortedDictionary<string, JsonValue>(StringComparer.Ordinal);
+ AddRange(items);
+ }
+
+ public override int Count
+ {
+ get { return _map.Count; }
+ }
+
+ public IEnumerator<JsonPair> GetEnumerator()
+ {
+ return _map.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _map.GetEnumerator();
+ }
+
+ public override sealed JsonValue this[string key]
+ {
+ get { return _map[key]; }
+ set { _map[key] = value; }
+ }
+
+ public override JsonType JsonType
+ {
+ get { return JsonType.Object; }
+ }
+
+ public ICollection<string> Keys
+ {
+ get { return _map.Keys; }
+ }
+
+ public ICollection<JsonValue> Values
+ {
+ get { return _map.Values; }
+ }
+
+ public void Add(string key, JsonValue value)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ _map.Add(key, value);
+ }
+
+ public void Add(JsonPair pair)
+ {
+ Add(pair.Key, pair.Value);
+ }
+
+ public void AddRange(JsonPairEnumerable items)
+ {
+ if (items == null)
+ throw new ArgumentNullException("items");
+
+ foreach (var pair in items)
+ _map.Add(pair.Key, pair.Value);
+ }
+
+ public void AddRange(params JsonPair[] items)
+ {
+ AddRange((JsonPairEnumerable)items);
+ }
+
+ public void Clear()
+ {
+ _map.Clear();
+ }
+
+ bool ICollection<JsonPair>.Contains(JsonPair item)
+ {
+ return (_map as ICollection<JsonPair>).Contains(item);
+ }
+
+ bool ICollection<JsonPair>.Remove(JsonPair item)
+ {
+ return (_map as ICollection<JsonPair>).Remove(item);
+ }
+
+ public override bool ContainsKey(string key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ return _map.ContainsKey(key);
+ }
+
+ public void CopyTo(JsonPair[] array, int arrayIndex)
+ {
+ (_map as ICollection<JsonPair>).CopyTo(array, arrayIndex);
+ }
+
+ public bool Remove(string key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ return _map.Remove(key);
+ }
+
+ bool ICollection<JsonPair>.IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public override void Save(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException("stream");
+ stream.WriteByte((byte)'{');
+ foreach (JsonPair pair in _map)
+ {
+ stream.WriteByte((byte)'"');
+ byte[] bytes = Encoding.UTF8.GetBytes(EscapeString(pair.Key));
+ stream.Write(bytes, 0, bytes.Length);
+ stream.WriteByte((byte)'"');
+ stream.WriteByte((byte)',');
+ stream.WriteByte((byte)' ');
+ if (pair.Value == null)
+ {
+ stream.WriteByte((byte)'n');
+ stream.WriteByte((byte)'u');
+ stream.WriteByte((byte)'l');
+ stream.WriteByte((byte)'l');
+ }
+ else
+ pair.Value.Save(stream);
+ }
+ stream.WriteByte((byte)'}');
+ }
+
+ public bool TryGetValue(string key, out JsonValue value)
+ {
+ return _map.TryGetValue(key, out value);
+ }
+ }
}
{
public class JsonPrimitive : JsonValue
{
- object value;
+ private object _value;
public JsonPrimitive(bool value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(byte value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(char value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(decimal value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(double value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(float value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(int value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(long value)
{
- this.value = value;
+ _value = value;
}
[CLSCompliant(false)]
public JsonPrimitive(sbyte value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(short value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(string value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(DateTime value)
{
- this.value = value;
+ _value = value;
}
[CLSCompliant(false)]
public JsonPrimitive(uint value)
{
- this.value = value;
+ _value = value;
}
[CLSCompliant(false)]
public JsonPrimitive(ulong value)
{
- this.value = value;
+ _value = value;
}
[CLSCompliant(false)]
public JsonPrimitive(ushort value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(DateTimeOffset value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(Guid value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(TimeSpan value)
{
- this.value = value;
+ _value = value;
}
public JsonPrimitive(Uri value)
{
- this.value = value;
+ _value = value;
}
internal object Value
{
- get { return value; }
+ get { return _value; }
}
public override JsonType JsonType
get
{
return
- value == null || value.GetType() == typeof(char) || value.GetType() == typeof(string) || value.GetType() == typeof(DateTime) || value.GetType() == typeof(object) ? JsonType.String : // DateTimeOffset || Guid || TimeSpan || Uri
- value.GetType() == typeof(bool) ? JsonType.Boolean :
+ _value == null || _value.GetType() == typeof(char) || _value.GetType() == typeof(string) || _value.GetType() == typeof(DateTime) || _value.GetType() == typeof(object) ? JsonType.String : // DateTimeOffset || Guid || TimeSpan || Uri
+ _value.GetType() == typeof(bool) ? JsonType.Boolean :
JsonType.Number;
}
}
switch (JsonType)
{
case JsonType.Boolean:
- if ((bool)value)
+ if ((bool)_value)
stream.Write(s_trueBytes, 0, 4);
else
stream.Write(s_falseBytes, 0, 5);
break;
case JsonType.String:
stream.WriteByte((byte)'\"');
- byte[] bytes = Encoding.UTF8.GetBytes(EscapeString(value.ToString()));
+ byte[] bytes = Encoding.UTF8.GetBytes(EscapeString(_value.ToString()));
stream.Write(bytes, 0, bytes.Length);
stream.WriteByte((byte)'\"');
break;
switch (JsonType)
{
case JsonType.String:
- if (value is string || value == null)
- return (string)value;
- if (value is char)
- return value.ToString();
- throw new NotImplementedException("GetFormattedString from value type " + value.GetType());
+ if (_value is string || _value == null)
+ return (string)_value;
+ if (_value is char)
+ return _value.ToString();
+ throw new NotImplementedException("GetFormattedString from value type " + _value.GetType());
case JsonType.Number:
string s;
- if (value is float || value is double)
+ if (_value is float || _value is double)
// Use "round-trip" format
- s = ((IFormattable)value).ToString("R", NumberFormatInfo.InvariantInfo);
+ s = ((IFormattable)_value).ToString("R", NumberFormatInfo.InvariantInfo);
else
- s = ((IFormattable)value).ToString("G", NumberFormatInfo.InvariantInfo);
+ s = ((IFormattable)_value).ToString("G", NumberFormatInfo.InvariantInfo);
if (s == "NaN" || s == "Infinity" || s == "-Infinity")
return "\"" + s + "\"";
else
namespace System.Json
{
- public enum JsonType
- {
- String,
- Number,
- Object,
- Array,
- Boolean,
- }
+ public enum JsonType
+ {
+ String,
+ Number,
+ Object,
+ Array,
+ Boolean,
+ }
}
namespace System.Json
{
public abstract class JsonValue : IEnumerable
- {
- public static JsonValue Load (Stream stream)
- {
+ {
+ public static JsonValue Load(Stream stream)
+ {
if (stream == null)
throw new ArgumentNullException(nameof(stream));
- return Load (new StreamReader (stream, true));
- }
+ return Load(new StreamReader(stream, true));
+ }
- public static JsonValue Load (TextReader textReader)
- {
+ public static JsonValue Load(TextReader textReader)
+ {
if (textReader == null)
throw new ArgumentNullException(nameof(textReader));
- var ret = new JavaScriptReader (textReader, true).Read ();
-
- return ToJsonValue (ret);
- }
-
- static IEnumerable<KeyValuePair<string,JsonValue>> ToJsonPairEnumerable (IEnumerable<KeyValuePair<string,object>> kvpc)
- {
- foreach (var kvp in kvpc)
- yield return new KeyValuePair<string,JsonValue> (kvp.Key, ToJsonValue (kvp.Value));
- }
-
- static IEnumerable<JsonValue> ToJsonValueEnumerable (IEnumerable<object> arr)
- {
- foreach (var obj in arr)
- yield return ToJsonValue (obj);
- }
-
- static JsonValue ToJsonValue (object ret)
- {
- if (ret == null)
- return null;
- var kvpc = ret as IEnumerable<KeyValuePair<string,object>>;
- if (kvpc != null)
- return new JsonObject (ToJsonPairEnumerable (kvpc));
- var arr = ret as IEnumerable<object>;
- if (arr != null)
- return new JsonArray (ToJsonValueEnumerable (arr));
-
- if (ret is bool)
- return new JsonPrimitive ((bool) ret);
- if (ret is byte)
- return new JsonPrimitive ((byte) ret);
- if (ret is char)
- return new JsonPrimitive ((char) ret);
- if (ret is decimal)
- return new JsonPrimitive ((decimal) ret);
- if (ret is double)
- return new JsonPrimitive ((double) ret);
- if (ret is float)
- return new JsonPrimitive ((float) ret);
- if (ret is int)
- return new JsonPrimitive ((int) ret);
- if (ret is long)
- return new JsonPrimitive ((long) ret);
- if (ret is sbyte)
- return new JsonPrimitive ((sbyte) ret);
- if (ret is short)
- return new JsonPrimitive ((short) ret);
- if (ret is string)
- return new JsonPrimitive ((string) ret);
- if (ret is uint)
- return new JsonPrimitive ((uint) ret);
- if (ret is ulong)
- return new JsonPrimitive ((ulong) ret);
- if (ret is ushort)
- return new JsonPrimitive ((ushort) ret);
- if (ret is DateTime)
- return new JsonPrimitive ((DateTime) ret);
- if (ret is DateTimeOffset)
- return new JsonPrimitive ((DateTimeOffset) ret);
- if (ret is Guid)
- return new JsonPrimitive ((Guid) ret);
- if (ret is TimeSpan)
- return new JsonPrimitive ((TimeSpan) ret);
- if (ret is Uri)
- return new JsonPrimitive ((Uri) ret);
- throw new NotSupportedException (string.Format ("Unexpected parser return type: {0}", ret.GetType ()));
- }
-
- public static JsonValue Parse (string jsonString)
- {
+ var ret = new JavaScriptReader(textReader, true).Read();
+
+ return ToJsonValue(ret);
+ }
+
+ private static IEnumerable<KeyValuePair<string, JsonValue>> ToJsonPairEnumerable(IEnumerable<KeyValuePair<string, object>> kvpc)
+ {
+ foreach (var kvp in kvpc)
+ yield return new KeyValuePair<string, JsonValue>(kvp.Key, ToJsonValue(kvp.Value));
+ }
+
+ private static IEnumerable<JsonValue> ToJsonValueEnumerable(IEnumerable<object> arr)
+ {
+ foreach (var obj in arr)
+ yield return ToJsonValue(obj);
+ }
+
+ private static JsonValue ToJsonValue(object ret)
+ {
+ if (ret == null)
+ return null;
+ var kvpc = ret as IEnumerable<KeyValuePair<string, object>>;
+ if (kvpc != null)
+ return new JsonObject(ToJsonPairEnumerable(kvpc));
+ var arr = ret as IEnumerable<object>;
+ if (arr != null)
+ return new JsonArray(ToJsonValueEnumerable(arr));
+
+ if (ret is bool)
+ return new JsonPrimitive((bool)ret);
+ if (ret is byte)
+ return new JsonPrimitive((byte)ret);
+ if (ret is char)
+ return new JsonPrimitive((char)ret);
+ if (ret is decimal)
+ return new JsonPrimitive((decimal)ret);
+ if (ret is double)
+ return new JsonPrimitive((double)ret);
+ if (ret is float)
+ return new JsonPrimitive((float)ret);
+ if (ret is int)
+ return new JsonPrimitive((int)ret);
+ if (ret is long)
+ return new JsonPrimitive((long)ret);
+ if (ret is sbyte)
+ return new JsonPrimitive((sbyte)ret);
+ if (ret is short)
+ return new JsonPrimitive((short)ret);
+ if (ret is string)
+ return new JsonPrimitive((string)ret);
+ if (ret is uint)
+ return new JsonPrimitive((uint)ret);
+ if (ret is ulong)
+ return new JsonPrimitive((ulong)ret);
+ if (ret is ushort)
+ return new JsonPrimitive((ushort)ret);
+ if (ret is DateTime)
+ return new JsonPrimitive((DateTime)ret);
+ if (ret is DateTimeOffset)
+ return new JsonPrimitive((DateTimeOffset)ret);
+ if (ret is Guid)
+ return new JsonPrimitive((Guid)ret);
+ if (ret is TimeSpan)
+ return new JsonPrimitive((TimeSpan)ret);
+ if (ret is Uri)
+ return new JsonPrimitive((Uri)ret);
+ throw new NotSupportedException(string.Format("Unexpected parser return type: {0}", ret.GetType()));
+ }
+
+ public static JsonValue Parse(string jsonString)
+ {
if (jsonString == null)
throw new ArgumentNullException(nameof(jsonString));
- return Load (new StringReader (jsonString));
- }
-
- public virtual int Count {
- get { throw new InvalidOperationException (); }
- }
-
- public abstract JsonType JsonType { get; }
-
- public virtual JsonValue this [int index] {
- get { throw new InvalidOperationException (); }
- set { throw new InvalidOperationException (); }
- }
-
- public virtual JsonValue this [string key] {
- get { throw new InvalidOperationException (); }
- set { throw new InvalidOperationException (); }
- }
-
- public virtual bool ContainsKey (string key)
- {
- throw new InvalidOperationException ();
- }
-
- public virtual void Save (Stream stream)
- {
- if (stream == null)
- throw new ArgumentNullException ("stream");
- Save (new StreamWriter (stream));
- }
-
- public virtual void Save (TextWriter textWriter)
- {
- if (textWriter == null)
- throw new ArgumentNullException ("textWriter");
- SaveInternal (textWriter);
- }
-
- void SaveInternal (TextWriter w)
- {
- switch (JsonType) {
- case JsonType.Object:
- w.Write ('{');
- bool following = false;
- foreach (JsonPair pair in ((JsonObject) this)) {
- if (following)
- w.Write (", ");
- w.Write ('\"');
- w.Write (EscapeString (pair.Key));
- w.Write ("\": ");
- if (pair.Value == null)
- w.Write ("null");
- else
- pair.Value.SaveInternal (w);
- following = true;
- }
- w.Write ('}');
- break;
- case JsonType.Array:
- w.Write ('[');
- following = false;
- foreach (JsonValue v in ((JsonArray) this)) {
- if (following)
- w.Write (", ");
- if (v != null)
- v.SaveInternal (w);
- else
- w.Write ("null");
- following = true;
- }
- w.Write (']');
- break;
- case JsonType.Boolean:
- w.Write ((bool) this ? "true" : "false");
- break;
- case JsonType.String:
- w.Write ('"');
- w.Write (EscapeString (((JsonPrimitive) this).GetFormattedString ()));
- w.Write ('"');
- break;
- default:
- w.Write (((JsonPrimitive) this).GetFormattedString ());
- break;
- }
- }
-
- public override string ToString ()
- {
- StringWriter sw = new StringWriter ();
- Save (sw);
- return sw.ToString ();
- }
-
- IEnumerator IEnumerable.GetEnumerator ()
- {
- throw new InvalidOperationException ();
- }
-
- // Characters which have to be escaped:
- // - Required by JSON Spec: Control characters, '"' and '\\'
- // - Broken surrogates to make sure the JSON string is valid Unicode
- // (and can be encoded as UTF8)
- // - JSON does not require U+2028 and U+2029 to be escaped, but
- // JavaScript does require this:
- // http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character/9168133#9168133
- // - '/' also does not have to be escaped, but escaping it when
- // preceeded by a '<' avoids problems with JSON in HTML <script> tags
- bool NeedEscape (string src, int i) {
- char c = src [i];
- return c < 32 || c == '"' || c == '\\'
- // Broken lead surrogate
- || (c >= '\uD800' && c <= '\uDBFF' &&
- (i == src.Length - 1 || src [i + 1] < '\uDC00' || src [i + 1] > '\uDFFF'))
- // Broken tail surrogate
- || (c >= '\uDC00' && c <= '\uDFFF' &&
- (i == 0 || src [i - 1] < '\uD800' || src [i - 1] > '\uDBFF'))
- // To produce valid JavaScript
- || c == '\u2028' || c == '\u2029'
- // Escape "</" for <script> tags
- || (c == '/' && i > 0 && src [i - 1] == '<');
- }
-
- internal string EscapeString (string src)
- {
- if (src == null)
- return null;
-
- for (int i = 0; i < src.Length; i++)
- if (NeedEscape (src, i)) {
- var sb = new StringBuilder ();
- if (i > 0)
- sb.Append (src, 0, i);
- return DoEscapeString (sb, src, i);
- }
- return src;
- }
-
- string DoEscapeString (StringBuilder sb, string src, int cur)
- {
- int start = cur;
- for (int i = cur; i < src.Length; i++)
- if (NeedEscape (src, i)) {
- sb.Append (src, start, i - start);
- switch (src [i]) {
- case '\b': sb.Append ("\\b"); break;
- case '\f': sb.Append ("\\f"); break;
- case '\n': sb.Append ("\\n"); break;
- case '\r': sb.Append ("\\r"); break;
- case '\t': sb.Append ("\\t"); break;
- case '\"': sb.Append ("\\\""); break;
- case '\\': sb.Append ("\\\\"); break;
- case '/': sb.Append ("\\/"); break;
- default:
- sb.Append ("\\u");
- sb.Append (((int) src [i]).ToString ("x04"));
- break;
- }
- start = i + 1;
- }
- sb.Append (src, start, src.Length - start);
- return sb.ToString ();
- }
-
- // CLI -> JsonValue
-
- public static implicit operator JsonValue (bool value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (byte value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (char value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (decimal value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (double value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (float value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (int value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (long value)
- {
- return new JsonPrimitive (value);
- }
+ return Load(new StringReader(jsonString));
+ }
+
+ public virtual int Count
+ {
+ get { throw new InvalidOperationException(); }
+ }
+
+ public abstract JsonType JsonType { get; }
+
+ public virtual JsonValue this[int index]
+ {
+ get { throw new InvalidOperationException(); }
+ set { throw new InvalidOperationException(); }
+ }
+
+ public virtual JsonValue this[string key]
+ {
+ get { throw new InvalidOperationException(); }
+ set { throw new InvalidOperationException(); }
+ }
+
+ public virtual bool ContainsKey(string key)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public virtual void Save(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException("stream");
+ Save(new StreamWriter(stream));
+ }
+
+ public virtual void Save(TextWriter textWriter)
+ {
+ if (textWriter == null)
+ throw new ArgumentNullException("textWriter");
+ SaveInternal(textWriter);
+ }
+
+ private void SaveInternal(TextWriter w)
+ {
+ switch (JsonType)
+ {
+ case JsonType.Object:
+ w.Write('{');
+ bool following = false;
+ foreach (JsonPair pair in ((JsonObject)this))
+ {
+ if (following)
+ w.Write(", ");
+ w.Write('\"');
+ w.Write(EscapeString(pair.Key));
+ w.Write("\": ");
+ if (pair.Value == null)
+ w.Write("null");
+ else
+ pair.Value.SaveInternal(w);
+ following = true;
+ }
+ w.Write('}');
+ break;
+ case JsonType.Array:
+ w.Write('[');
+ following = false;
+ foreach (JsonValue v in ((JsonArray)this))
+ {
+ if (following)
+ w.Write(", ");
+ if (v != null)
+ v.SaveInternal(w);
+ else
+ w.Write("null");
+ following = true;
+ }
+ w.Write(']');
+ break;
+ case JsonType.Boolean:
+ w.Write((bool)this ? "true" : "false");
+ break;
+ case JsonType.String:
+ w.Write('"');
+ w.Write(EscapeString(((JsonPrimitive)this).GetFormattedString()));
+ w.Write('"');
+ break;
+ default:
+ w.Write(((JsonPrimitive)this).GetFormattedString());
+ break;
+ }
+ }
+
+ public override string ToString()
+ {
+ StringWriter sw = new StringWriter();
+ Save(sw);
+ return sw.ToString();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ throw new InvalidOperationException();
+ }
+
+ // Characters which have to be escaped:
+ // - Required by JSON Spec: Control characters, '"' and '\\'
+ // - Broken surrogates to make sure the JSON string is valid Unicode
+ // (and can be encoded as UTF8)
+ // - JSON does not require U+2028 and U+2029 to be escaped, but
+ // JavaScript does require this:
+ // http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character/9168133#9168133
+ // - '/' also does not have to be escaped, but escaping it when
+ // preceeded by a '<' avoids problems with JSON in HTML <script> tags
+ private bool NeedEscape(string src, int i)
+ {
+ char c = src[i];
+ return c < 32 || c == '"' || c == '\\'
+ // Broken lead surrogate
+ || (c >= '\uD800' && c <= '\uDBFF' &&
+ (i == src.Length - 1 || src[i + 1] < '\uDC00' || src[i + 1] > '\uDFFF'))
+ // Broken tail surrogate
+ || (c >= '\uDC00' && c <= '\uDFFF' &&
+ (i == 0 || src[i - 1] < '\uD800' || src[i - 1] > '\uDBFF'))
+ // To produce valid JavaScript
+ || c == '\u2028' || c == '\u2029'
+ // Escape "</" for <script> tags
+ || (c == '/' && i > 0 && src[i - 1] == '<');
+ }
+
+ internal string EscapeString(string src)
+ {
+ if (src == null)
+ return null;
+
+ for (int i = 0; i < src.Length; i++)
+ if (NeedEscape(src, i))
+ {
+ var sb = new StringBuilder();
+ if (i > 0)
+ sb.Append(src, 0, i);
+ return DoEscapeString(sb, src, i);
+ }
+ return src;
+ }
+
+ private string DoEscapeString(StringBuilder sb, string src, int cur)
+ {
+ int start = cur;
+ for (int i = cur; i < src.Length; i++)
+ if (NeedEscape(src, i))
+ {
+ sb.Append(src, start, i - start);
+ switch (src[i])
+ {
+ case '\b': sb.Append("\\b"); break;
+ case '\f': sb.Append("\\f"); break;
+ case '\n': sb.Append("\\n"); break;
+ case '\r': sb.Append("\\r"); break;
+ case '\t': sb.Append("\\t"); break;
+ case '\"': sb.Append("\\\""); break;
+ case '\\': sb.Append("\\\\"); break;
+ case '/': sb.Append("\\/"); break;
+ default:
+ sb.Append("\\u");
+ sb.Append(((int)src[i]).ToString("x04"));
+ break;
+ }
+ start = i + 1;
+ }
+ sb.Append(src, start, src.Length - start);
+ return sb.ToString();
+ }
+
+ // CLI -> JsonValue
+
+ public static implicit operator JsonValue(bool value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(byte value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(char value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(decimal value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(double value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(float value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(int value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(long value)
+ {
+ return new JsonPrimitive(value);
+ }
[CLSCompliant(false)]
- public static implicit operator JsonValue (sbyte value)
- {
- return new JsonPrimitive (value);
- }
+ public static implicit operator JsonValue(sbyte value)
+ {
+ return new JsonPrimitive(value);
+ }
- public static implicit operator JsonValue (short value)
- {
- return new JsonPrimitive (value);
- }
+ public static implicit operator JsonValue(short value)
+ {
+ return new JsonPrimitive(value);
+ }
- public static implicit operator JsonValue (string value)
- {
- return new JsonPrimitive (value);
- }
+ public static implicit operator JsonValue(string value)
+ {
+ return new JsonPrimitive(value);
+ }
[CLSCompliant(false)]
- public static implicit operator JsonValue (uint value)
+ public static implicit operator JsonValue(uint value)
{
- return new JsonPrimitive (value);
- }
+ return new JsonPrimitive(value);
+ }
[CLSCompliant(false)]
- public static implicit operator JsonValue (ulong value)
+ public static implicit operator JsonValue(ulong value)
{
- return new JsonPrimitive (value);
- }
+ return new JsonPrimitive(value);
+ }
[CLSCompliant(false)]
- public static implicit operator JsonValue (ushort value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (DateTime value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (DateTimeOffset value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (Guid value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (TimeSpan value)
- {
- return new JsonPrimitive (value);
- }
-
- public static implicit operator JsonValue (Uri value)
- {
- return new JsonPrimitive (value);
- }
-
- // JsonValue -> CLI
-
- public static implicit operator bool (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToBoolean (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
-
- public static implicit operator byte (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToByte (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
-
- public static implicit operator char (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToChar (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
-
- public static implicit operator decimal (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToDecimal (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
-
- public static implicit operator double (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToDouble (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
-
- public static implicit operator float (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToSingle (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
-
- public static implicit operator int (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToInt32 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
-
- public static implicit operator long (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToInt64 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
+ public static implicit operator JsonValue(ushort value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(DateTime value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(DateTimeOffset value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(Guid value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(TimeSpan value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ public static implicit operator JsonValue(Uri value)
+ {
+ return new JsonPrimitive(value);
+ }
+
+ // JsonValue -> CLI
+
+ public static implicit operator bool (JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToBoolean(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
+
+ public static implicit operator byte (JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToByte(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
+
+ public static implicit operator char (JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToChar(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
+
+ public static implicit operator decimal (JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToDecimal(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
+
+ public static implicit operator double (JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToDouble(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
+
+ public static implicit operator float (JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToSingle(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
+
+ public static implicit operator int (JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToInt32(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
+
+ public static implicit operator long (JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToInt64(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
[CLSCompliant(false)]
- public static implicit operator sbyte (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToSByte (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
-
- public static implicit operator short (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToInt16 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
-
- public static implicit operator string (JsonValue value)
- {
- if (value == null)
- return null;
- return (string) ((JsonPrimitive) value).Value;
- }
+ public static implicit operator sbyte (JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToSByte(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
+
+ public static implicit operator short (JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToInt16(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
+
+ public static implicit operator string (JsonValue value)
+ {
+ if (value == null)
+ return null;
+ return (string)((JsonPrimitive)value).Value;
+ }
[CLSCompliant(false)]
- public static implicit operator uint (JsonValue value)
+ public static implicit operator uint (JsonValue value)
{
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToUInt32 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToUInt32(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
[CLSCompliant(false)]
- public static implicit operator ulong (JsonValue value)
+ public static implicit operator ulong (JsonValue value)
{
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToUInt64(((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToUInt64(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
[CLSCompliant(false)]
- public static implicit operator ushort (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return Convert.ToUInt16 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
- }
-
- public static implicit operator DateTime (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return (DateTime) ((JsonPrimitive) value).Value;
- }
-
- public static implicit operator DateTimeOffset (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return (DateTimeOffset) ((JsonPrimitive) value).Value;
- }
-
- public static implicit operator TimeSpan (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return (TimeSpan) ((JsonPrimitive) value).Value;
- }
-
- public static implicit operator Guid (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return (Guid) ((JsonPrimitive) value).Value;
- }
-
- public static implicit operator Uri (JsonValue value)
- {
- if (value == null)
- throw new ArgumentNullException (nameof(value));
- return (Uri) ((JsonPrimitive) value).Value;
- }
- }
+ public static implicit operator ushort (JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return Convert.ToUInt16(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+ }
+
+ public static implicit operator DateTime(JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return (DateTime)((JsonPrimitive)value).Value;
+ }
+
+ public static implicit operator DateTimeOffset(JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return (DateTimeOffset)((JsonPrimitive)value).Value;
+ }
+
+ public static implicit operator TimeSpan(JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return (TimeSpan)((JsonPrimitive)value).Value;
+ }
+
+ public static implicit operator Guid(JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return (Guid)((JsonPrimitive)value).Value;
+ }
+
+ public static implicit operator Uri(JsonValue value)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ return (Uri)((JsonPrimitive)value).Value;
+ }
+ }
}
}
// Parse a json string and compare to the expected value
- void CheckDouble(double expected, string json)
+ private void CheckDouble(double expected, string json)
{
double jvalue = (double)JsonValue.Parse(json);
Assert.Equal(expected, jvalue);
}
// Convert a number to json and parse the string, then compare the result to the original value
- void CheckDouble(double number)
+ private void CheckDouble(double number)
{
double jvalue = (double)JsonValue.Parse(new JsonPrimitive(number).ToString());
Assert.Equal(number, jvalue); // should be exactly the same
}
// Convert a string to json and parse the string, then compare the result to the original value
- void CheckString(string str)
+ private void CheckString(string str)
{
var json = new JsonPrimitive(str).ToString();
// Check whether the string is valid Unicode (will throw for broken surrogate pairs)