public JsonTextReader(TextReader reader) { if (reader == null) throw new ArgumentNullException("reader"); _parser = new TextParser(reader.ReadToEnd()); _stack = new Stack(); _stack.Push(ParseMethod); }
private object Parse(TextParser parser) { Debug.Assert(parser != null); // // Fault-in an AST strategy if one wasn't supplied thus far. // if (_output == null) _output = new ParserOutput(); // // Parse and return the next object found. // return NextObject(parser); }
private object Parse(TextParser parser) { Debug.Assert(parser != null); // // Get the names from the first row. If no names are found then // bail out with a null. // ICollection nameCollection = (ICollection) ParseRowToArray(parser); if (nameCollection == null) return null; // // Turn the values in the names collection into an array of // string. Note, we need to handle this quite generically since // we cannot assume what objects were returned by the // IParserOutput implementation. // int i = 0; string[] names = new string[nameCollection.Count]; foreach (object nameValue in nameCollection) names[i++] = nameValue.ToString(); // // Finally, build an array of objects, where each object comes // from a row, and then return the resulting array. // IParserOutput output = Output; output.StartArray(); object item = ParseRowToObject(parser, names); while (item != null) { output.ArrayPut(item); item = ParseRowToObject(parser, names); } return output.EndArray(); }
/// <summary> /// Get the next value. The value can be wrapped in quotes. /// The value can be empty. /// </summary> private string GetValue(TextParser parser) { char ch; do { ch = parser.Next(); } while (ch <= ' ' && ch != TextParser.EOF); switch (ch) { case TextParser.EOF: return null; case '"': case '\'': return parser.NextString(ch); case ',': parser.Back(); return ""; default: parser.Back(); return parser.NextTo(','); } }
/// <summary> /// Parses the values from a row into an object given a set of names /// to use for the members. /// </summary> private object ParseRowToObject(TextParser parser, string[] names) { Debug.Assert(parser != null); if (names == null) return null; ICollection collection = (ICollection) ParseRowToArray(parser); if (collection == null) return null; object[] values = new object[collection.Count]; collection.CopyTo(values, 0); IParserOutput output = Output; output.StartObject(); for (int i = 0; i < Math.Min(names.Length, values.Length); i++) output.ObjectPut(names[i], values[i]); return output.EndObject(); }
private object ParseRowToArray(TextParser parser) { Debug.Assert(parser != null); string value = GetValue(parser); if (value == null) return null; IParserOutput output = Output; output.StartArray(); do { output.ArrayPut(value); while (true) { char ch = parser.Next(); if (ch == ',') { break; } else if (ch != ' ') { if (ch == '\n' || ch == '\r' || ch == TextParser.EOF) return output.EndArray(); throw new ParseException("Bad character '" + ch.ToString() + "' (" + ((int) ch).ToString(CultureInfo.InvariantCulture) + ")."); } } value = GetValue(parser); } while (value != null); return output.EndArray(); }
/// <summary> /// Get the next char in the string, skipping whitespace /// and comments (slashslash and slashstar). /// </summary> /// <returns>A character, or 0 if there are no more characters.</returns> private char NextClean(TextParser parser) { Debug.Assert(parser != null); while (true) { char ch = parser.Next(); if (ch == '/') { switch (parser.Next()) { case '/' : { do { ch = parser.Next(); } while (ch != '\n' && ch != '\r' && ch != EOF); break; } case '*' : { while (true) { ch = parser.Next(); if (ch == EOF) throw new ParseException("Unclosed comment."); if (ch == '*') { if (parser.Next() == '/') break; parser.Back(); } } break; } default : { parser.Back(); return '/'; } } } else if (ch == EOF || ch > ' ') { return ch; } } }
private object ParseObject(TextParser parser) { Debug.Assert(parser != null); if (parser.Next() == '%') parser.Restart(Unescape(parser.Source), parser.Index); parser.Back(); if (NextClean(parser) != '{') throw new ParseException("An object must begin with '{'."); _output.StartObject(); char ch = NextClean(parser); while (ch != '}') { string memberName; switch (ch) { case JsonParser.EOF : throw new ParseException("An object must end with '}'."); case '}' : continue; default : { parser.Back(); memberName = NextObject(parser).ToString(); break; } } if (NextClean(parser) != ':') throw new ParseException("Expected a ':' after a key."); object memberValue = NextObject(parser); _output.ObjectPut(memberName, memberValue); switch (ch = NextClean(parser)) { case ',' : { if ((ch = NextClean(parser)) == '}') continue; parser.Back(); break; } case '}' : continue; default : throw new ParseException("Expected a ',' or '}'."); } ch = NextClean(parser); } return _output.EndObject(); }
private object ParseArray(TextParser parser) { Debug.Assert(parser != null); if (NextClean(parser) != '[') throw new ParseException("An array must start with '['."); _output.StartArray(); if (NextClean(parser) != ']') { parser.Back(); bool end = false; do { _output.ArrayPut(NextObject(parser)); switch (NextClean(parser)) { case ',' : { if (NextClean(parser) == ']') end = true; else parser.Back(); break; } case ']' : { end = true; break; } default : throw new ParseException("Expected a ',' or ']'."); } } while (!end); } return _output.EndArray(); }
/// <summary> /// Gets the next value as object. The value can be a Boolean, a Double, /// an Integer, an object array, a JObject, a String, or /// JObject.NULL. /// </summary> private object NextObject(TextParser parser) { Debug.Assert(parser != null); char ch = NextClean(parser); // // String // if (ch == '"' || ch == '\'') return _output.ToStringPrimitive(parser.NextString(ch)); // // Object // if (ch == '{') { parser.Back(); return ParseObject(parser); } // // JSON Array // if (ch == '[') { parser.Back(); return ParseArray(parser); } StringBuilder sb = new StringBuilder(); char b = ch; while (ch >= ' ' && ch != ':' && ch != ',' && ch != ']' && ch != '}' && ch != '/') { sb.Append(ch); ch = parser.Next(); } parser.Back(); string s = sb.ToString().Trim(); if (s == "true") return _output.TruePrimitive; if (s == "false") return _output.FalsePrimitive; if (s == "null") return _output.NullPrimitive; if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') { object number = _output.ToNumberPrimitive(s); if (number == null) throw new ParseException(string.Format("Cannot convert '{0}' to a number.", s)); return number; } if (s.Length == 0) throw new ParseException("Missing value."); return s; }