protected override bool OnObjectPropertyDetected(string propertyName, JsonReader reader) { var x = new EmptyJson { Accumulate = this.Accumulate }; if (Accumulate) { if (count > 0) { buffer.Append(", "); } buffer.AppendFormat("\"{0}\": {{", propertyName); } x.ReadJson(reader); if (Accumulate) { buffer.Append(x.JsonString); buffer.Append('}'); count++; } return(true); }
private void ReadJsonInternal(string json, JsonReader givenReader) { JsonReader reader; if (givenReader == null) { reader = new JsonReader(json); } else { reader = givenReader; } var state = 1; var chContainer = '"'; var propertyName = new CharBuffer(PropertyNameBufferSize); var propertyValue = new CharBuffer(PropertyValueBufferSize); var unicodeEscapeCode = new CharBuffer(); var arrayItem = new CharBuffer(); int code = 0; while (!reader.Finished) { var ch = reader.Next(); switch (state) { case 1: if (Char.IsWhiteSpace(ch)) { continue; } if (ch == '{') { state = 2; continue; } if (ch == '[') { state = 20; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidCharacter, ch, "{ or ["); break; case 2: if (Char.IsWhiteSpace(ch)) { continue; } if (ch == '\'' || ch == '"') { chContainer = ch; state = 3; continue; } if (!Char.IsPunctuation(ch) && !Char.IsControl(ch)) { propertyName.Append(ch); state = 6; continue; } if (ch == '}') { goto exit_while; } ParseError(json, state, reader.Position, JsonParseError.InvalidCharacter, ch, "property name starter char"); break; case 3: if (ch == chContainer) { if (propertyName.Length == 0) { ParseError(json, state, reader.Position, JsonParseError.PropertyNameIsEmpty, ch, ""); } state = 7; continue; } if (ch == '\\') { state = 4; continue; } propertyName.Append(ch); break; case 4: if (ch.ExistsIn(new char[] { 'b', 'f', 'n', 'r', 't', '\\', '"', '\'', '/' })) { propertyName.Append(ch.Escape()); state = 3; continue; } if (ch == 'u' || ch == 'U') { state = 5; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidEscapeChar, ch, ""); break; case 5: if (ch.IsHexDigit()) { unicodeEscapeCode.Append(ch); continue; } code = int.Parse(unicodeEscapeCode.ToString(), System.Globalization.NumberStyles.HexNumber); propertyName.Append(char.ConvertFromUtf32(code)); unicodeEscapeCode.Reset(); reader.Store(); break; case 6: if (ch == ':' || Char.IsWhiteSpace(ch)) { if (ch != ':') { reader.Store(); state = 7; continue; } if (propertyName.Length != 0) { state = 8; continue; } else { ParseError(json, state, reader.Position, JsonParseError.PropertyNameIsEmpty, ch, ":"); } } propertyName.Append(ch); break; case 7: if (Char.IsWhiteSpace(ch)) { continue; } if (ch == ':') { state = 8; continue; } ParseError(json, state, reader.Position, JsonParseError.ColonExpected, ch, ":"); break; case 8: if (Char.IsWhiteSpace(ch)) { continue; } if (Char.IsLetter(ch)) { state = 9; propertyValue.Append(ch); continue; } if (Char.IsDigit(ch)) { state = 11; propertyValue.Append(ch); continue; } if (ch == '.') { state = 110; propertyValue.Append(ch); continue; } if (ch == '-' || ch == '+') { state = 12; propertyValue.Append(ch); continue; } if (ch == '"' || ch == '\'') { state = 17; chContainer = ch; continue; } if (ch == '[') { reader.Store(); if (!OnArrayPropertyDetected(propertyName.ToString(), reader)) { var x = new EmptyJsonArray(); x.ReadJson(reader); } propertyName.Reset(); propertyValue.Reset(); state = 10; continue; } if (ch == '{') { reader.Store(); if (!OnObjectPropertyDetected(propertyName.ToString(), reader)) { var x = new EmptyJson(); x.ReadJson(reader); } propertyName.Reset(); propertyValue.Reset(); state = 10; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidCharacter, ch, "{ | [ | ' | \" | - | + | letter | digit"); break; case 9: if (Char.IsLetter(ch)) { propertyValue.Append(ch); continue; } else { var value = propertyValue.ToString(); if (string.Compare(value, "true", false) == 0 || string.Compare(value, "false", false) == 0 || string.Compare(value, "null", false) == 0) { if (string.Compare(value, "true", false) == 0 || string.Compare(value, "false", false) == 0) { OnBasicPropertyDetected(propertyName.ToString(), value, JsonValueType.Boolean); } else { OnBasicPropertyDetected(propertyName.ToString(), value, JsonValueType.Null); } propertyName.Reset(); propertyValue.Reset(); reader.Store(); state = 10; continue; } else { ParseError(json, state, reader.Position, JsonParseError.InvalidPropertyValue, ch, "number | true | false | null | {array} | {object}"); } } break; case 10: if (Char.IsWhiteSpace(ch)) { continue; } if (ch == ',') { state = 2; continue; } if (ch == '}') { goto exit_while; } ParseError(json, state, reader.Position, JsonParseError.ExpectedCommaOrBrace, ch, "',' | '{'"); break; case 11: if (Char.IsDigit(ch)) { propertyValue.Append(ch); continue; } if (ch == '.') { propertyValue.Append(ch); state = 110; continue; } if (ch == 'e' || ch == 'E') { propertyValue.Append(ch); state = 13; continue; } OnBasicPropertyDetected(propertyName.ToString(), propertyValue.ToString(), JsonValueType.Number); propertyName.Reset(); propertyValue.Reset(); state = 10; reader.Store(); break; case 110: if (Char.IsDigit(ch)) { propertyValue.Append(ch); continue; } if (ch == 'e' || ch == 'E') { propertyValue.Append(ch); state = 13; continue; } OnBasicPropertyDetected(propertyName.ToString(), propertyValue.ToString(), JsonValueType.Number); propertyName.Reset(); propertyValue.Reset(); state = 10; reader.Store(); break; case 12: if (Char.IsWhiteSpace(ch)) { continue; } if (ch == '.' || Char.IsDigit(ch)) { propertyValue.Append(ch); state = 11; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidNumber, ch, ""); break; case 13: if (Char.IsDigit(ch)) { propertyValue.Append(ch); state = 14; continue; } if (ch == '-' || ch == '+') { propertyValue.Append(ch); state = 15; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidNumber, ch, ""); break; case 14: if (Char.IsDigit(ch)) { propertyValue.Append(ch); continue; } OnBasicPropertyDetected(propertyName.ToString(), propertyValue.ToString(), JsonValueType.Number); propertyName.Reset(); propertyValue.Reset(); reader.Store(); state = 10; break; case 15: if (Char.IsDigit(ch)) { propertyValue.Append(ch); state = 16; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidNumber, ch, ""); break; case 16: if (Char.IsDigit(ch)) { propertyValue.Append(ch); continue; } OnBasicPropertyDetected(propertyName.ToString(), propertyValue.ToString(), JsonValueType.Number); propertyName.Reset(); propertyValue.Reset(); reader.Store(); state = 10; break; case 17: if (ch == chContainer) { if (ch == '"') { OnBasicPropertyDetected(propertyName.ToString(), propertyValue.ToString(), JsonValueType.String); } else { OnBasicPropertyDetected(propertyName.ToString(), propertyValue.ToString(), JsonValueType.Char); } propertyName.Reset(); propertyValue.Reset(); state = 10; continue; } if (ch == '\\') { state = 18; continue; } propertyValue.Append(ch); break; case 18: if (ch.ExistsIn(new char[] { 'b', 'f', 'n', 'r', 't', '\\', '"', '\'', '/' })) { propertyValue.Append(ch.Escape()); state = 17; continue; } if (ch == 'u' || ch == 'U') { state = 19; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidEscapeChar, ch, ""); break; case 19: if (ch.IsHexDigit()) { unicodeEscapeCode.Append(ch); continue; } code = int.Parse(unicodeEscapeCode.ToString(), System.Globalization.NumberStyles.HexNumber); propertyValue.Append(char.ConvertFromUtf32(code)); unicodeEscapeCode.Reset(); state = 17; reader.Store(); break; case 20: if (Char.IsWhiteSpace(ch)) { continue; } if (Char.IsDigit(ch)) { arrayItem.Append(ch); state = 21; continue; } if (ch == '.') { arrayItem.Append(ch); state = 200; continue; } if (ch == '-' || ch == '+') { arrayItem.Append(ch); state = 23; continue; } if (ch == '"' || ch == '\'') { chContainer = ch; state = 28; continue; } if (Char.IsLetter(ch)) { arrayItem.Append(ch); state = 31; continue; } if (ch == ']') { reader.Store(); state = 22; continue; } if (ch == '[') { reader.Store(); arrayItem.Reset(); if (!OnArrayItemDetected(reader)) { var x = new EmptyJsonArray(); x.ReadJson(reader); } state = 22; continue; } if (ch == '{') { reader.Store(); arrayItem.Reset(); if (!OnObjectItemDetected(reader)) { var x = new EmptyJson(); x.ReadJson(reader); } state = 22; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidCharacter, ch, "{ | [ | ' | \" | - | + | letter | digit"); break; case 200: if (Char.IsDigit(ch)) { arrayItem.Append(ch); state = 210; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidCharacter, ch, "digit"); break; case 21: if (Char.IsDigit(ch)) { arrayItem.Append(ch); continue; } if (ch == 'e' || ch == 'E') { arrayItem.Append(ch); state = 24; continue; } if (ch == '.') { arrayItem.Append(ch); state = 210; continue; } OnBasicItemDetected(arrayItem.ToString(), JsonValueType.Number); arrayItem.Reset(); reader.Store(); state = 22; break; case 210: if (Char.IsDigit(ch)) { arrayItem.Append(ch); continue; } if (ch == 'e' || ch == 'E') { arrayItem.Append(ch); state = 24; continue; } OnBasicItemDetected(arrayItem.ToString(), JsonValueType.Number); arrayItem.Reset(); reader.Store(); state = 22; break; case 22: if (Char.IsWhiteSpace(ch)) { continue; } if (ch == ']') { goto exit_while; } if (ch == ',') { state = 20; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidCharacter, ch, ", | ]"); break; case 23: if (Char.IsWhiteSpace(ch)) { continue; } if (Char.IsDigit(ch)) { arrayItem.Append(ch); state = 21; continue; } if (ch == '.') { arrayItem.Append(ch); state = 210; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidNumber, ch, ""); break; case 24: if (Char.IsDigit(ch)) { arrayItem.Append(ch); state = 25; continue; } if (ch == '-' || ch == '+') { arrayItem.Append(ch); state = 26; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidNumber, ch, ""); break; case 25: if (Char.IsDigit(ch)) { arrayItem.Append(ch); continue; } OnBasicItemDetected(arrayItem.ToString(), JsonValueType.Number); arrayItem.Reset(); reader.Store(); state = 22; break; case 26: if (Char.IsDigit(ch)) { arrayItem.Append(ch); state = 27; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidNumber, ch, ""); break; case 27: if (Char.IsDigit(ch)) { arrayItem.Append(ch); continue; } OnBasicItemDetected(arrayItem.ToString(), JsonValueType.Number); arrayItem.Reset(); reader.Store(); state = 22; break; case 28: if (ch == chContainer) { if (ch == '"') { OnBasicItemDetected(arrayItem.ToString(), JsonValueType.String); } else { OnBasicItemDetected(arrayItem.ToString(), JsonValueType.Char); } arrayItem.Reset(); state = 22; continue; } if (ch == '\\') { state = 29; continue; } arrayItem.Append(ch); break; case 29: if (ch.ExistsIn(new char[] { 'b', 'f', 'n', 'r', 't', '\\', '"', '\'', '/' })) { arrayItem.Append(ch.Escape()); state = 28; continue; } if (ch == 'u' || ch == 'U') { state = 30; continue; } ParseError(json, state, reader.Position, JsonParseError.InvalidEscapeChar, ch, ""); break; case 30: if (Char.IsDigit(ch)) { unicodeEscapeCode.Append(ch); continue; } code = int.Parse(unicodeEscapeCode.ToString(), System.Globalization.NumberStyles.HexNumber); arrayItem.Append(char.ConvertFromUtf32(code)); unicodeEscapeCode.Reset(); state = 28; reader.Store(); break; case 31: if (Char.IsLetter(ch)) { arrayItem.Append(ch); continue; } var arrayValue = arrayItem.ToString(); if (string.Compare(arrayValue, "true", false) == 0 || string.Compare(arrayValue, "false", false) == 0 || string.Compare(arrayValue, "null", false) == 0) { if (string.Compare(arrayValue, "true", false) == 0 || string.Compare(arrayValue, "false", false) == 0) { OnBasicItemDetected(arrayValue, JsonValueType.Boolean); } else { OnBasicItemDetected(arrayValue, JsonValueType.Null); } arrayItem.Reset(); reader.Store(); state = 22; continue; } else { ParseError(json, state, reader.Position, JsonParseError.InvalidArrayItem, ch, "number | true | false | null | {array} | {object}"); } break; } } exit_while: if (givenReader == null) { return; } }