/// <summary> /// Put a value into this Json array /// </summary> /// <param name="o">The value to add to this Json array</param> /// <returns>This Json array</returns> public JSONArray Put(int index, JSONObject o) { items.Insert(index, o); return(this); }
/// <summary> /// Private method for parsing a Json string into a Json object /// </summary> /// <param name="json">The Json string to parse</param> /// <returns>A deserialized Json object</returns> private JSONObject ParseJSONObject(string json) { JSONObject jo = new JSONObject(); int bracketCounter = 0; int curlyBracketCounter = 0; bool hasEnteredObject = false; bool inLiteral = false; bool inNestedJsonObject = false; bool inNestedArray = false; bool expectingName = true; string currentFieldName = null; bool buildingPrimitiveValue = false; bool escapingCharacter = false; StringBuilder buffer = new StringBuilder(); //Loop through every character in the Json string for (int i = 0; i < json.Length; i++) { char c = json[i]; if (inLiteral && !(!escapingCharacter && c == '"')) { //Handle escape characters in string literals if (inLiteral && c == '\\') { if (escapingCharacter) { escapingCharacter = false; buffer.Append('\\'); } else { escapingCharacter = true; } } else if (c != '"') { //Look for the next character in an escape character if we are escaping if (escapingCharacter) { if (c == 'b') { buffer.Append('\b'); } else if (c == 'f') { buffer.Append('\f'); } else if (c == 'n') { buffer.Append('\n'); } else if (c == 'r') { buffer.Append('\r'); } else if (c == 't') { buffer.Append('\t'); } else if (c == '"') { buffer.Append('\"'); } else { //We were escaping a character but this isn't a valid one throw new MalformedJsonException(); } escapingCharacter = false; } else { //Add to the buffer if inside a literal buffer.Append(c); } } else if (c == '"' && escapingCharacter && inLiteral) { buffer.Append('"'); escapingCharacter = false; } } else if (inNestedJsonObject && c != '}' || inNestedArray && c != ']') { //Add to the buffer if inside a nested Json object buffer.Append(c); } else if (char.IsWhiteSpace(c)) { //Whitespace characters if (buildingPrimitiveValue && !inNestedJsonObject && !inNestedArray) { //This would mean we didn't enclose a literal and are looking for a value //The buffer should be a value jo.Put(currentFieldName, ParseValue(buffer.ToString())); buffer.Length = 0; expectingName = true; buildingPrimitiveValue = false; } } else if (c == '{') { bracketCounter++; if (bracketCounter == 1 && hasEnteredObject) { throw new MalformedJsonException(); } hasEnteredObject = true; if (bracketCounter > 1) { //This should only happen when expecting a value if (expectingName) { throw new MalformedJsonException(); } inNestedJsonObject = true; buffer.Append(c); } } else if (c == '}') { bracketCounter--; if (bracketCounter < 0) { throw new MalformedJsonException(); } else if (bracketCounter == 1) { if (inNestedJsonObject) { //This should only happen when expecting a value if (expectingName) { throw new MalformedJsonException(); } inNestedJsonObject = false; buffer.Append(c); //Parse the inner object and add it jo.Put(currentFieldName, ParseJSONObject(buffer.ToString())); buffer.Length = 0; //We need a name now expectingName = true; } } else if (bracketCounter == 0) { if (!expectingName && buildingPrimitiveValue) { //We weren't in an object and a bracket appeared //The object should be ending in this case and this is the final value jo.Put(currentFieldName, ParseValue(buffer.ToString())); buffer.Length = 0; expectingName = true; buildingPrimitiveValue = false; } } } else if (c == '[') { if (!hasEnteredObject) { throw new MalformedJsonException(); } curlyBracketCounter++; if (curlyBracketCounter > 0) { inNestedArray = true; //This should only happen when expecting a value if (expectingName) { throw new MalformedJsonException(); } inNestedArray = true; buffer.Append(c); } } else if (c == ']') { curlyBracketCounter--; if (curlyBracketCounter < 0) { throw new MalformedJsonException(); } else if (curlyBracketCounter == 0) { //This should only happen when expecting a value if (expectingName) { throw new MalformedJsonException(); } inNestedArray = false; buffer.Append(c); //Parse the inner object and add it jo.Put(currentFieldName, new JSONArray(buffer.ToString())); buffer.Length = 0; //We need a name now expectingName = true; } } else if (c == '"') { //Here we either just started or ended a literal inLiteral = !inLiteral; //If we're looking for a name and we just exited a literal if (!inLiteral) //If we just ended a literal... { if (expectingName) { //We were looking for a name, store it //Store the field name currentFieldName = buffer.ToString(); buffer.Length = 0; //Expecting value now expectingName = !expectingName; } else { //We were expecting a value so we must have a string literal jo.Put(currentFieldName, buffer.ToString()); buffer.Length = 0; //Next up is a name expectingName = true; } } } else if (c == ':') { //We should have already flipped the switch in the quote logic //So we could probably just ignore this if (expectingName) { throw new MalformedJsonException(); } } else if (c == ',') { if (!expectingName) { //This would mean we didn't enclose a literal and are looking for a value //The buffer should be a value jo.Put(currentFieldName, ParseValue(buffer.ToString())); buffer.Length = 0; expectingName = true; buildingPrimitiveValue = false; } } else { //Only accept other characters if in an object and looking for a value if (hasEnteredObject && !expectingName) { buffer.Append(c); //We are creating a primitive type buildingPrimitiveValue = true; } else { throw new MalformedJsonException(); } } } //parse complete return(jo); }
/// <summary> /// Put a value into this Json array /// </summary> /// <param name="o">The value to add to this Json array</param> /// <returns>This Json array</returns> public JSONArray Put(JSONObject o) { items.Add(o); return(this); }
/// <summary> /// Maps name to value, clobbering any existing name/value mapping with the same name /// </summary> /// <param name="name">The field name for the mapping</param> /// <param name="value">The value to be mapped to the field name</param> /// <returns>This json object with the mapping added</returns> public JSONObject Put(string name, JSONObject value) { items[name] = value; return(this); }