JSONObject.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. using System.Collections.Generic;
  2. using System.Text;
  3. using UnityEngine;
  4. /**
  5. * An object is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace).
  6. * Each name is followed by : (colon) and the name/value pairs are separated by , (comma).
  7. * @author zeh
  8. */
  9. public class JSONObject:JSONValue {
  10. // Constants
  11. private const char CHAR_START = '{';
  12. private const char CHAR_END = '}';
  13. private const char CHAR_KEY_SEPARATOR = ':';
  14. private const char CHAR_ITEM_SEPARATOR = ',';
  15. // Enums
  16. private enum ParsingState {
  17. Start,
  18. BeforeKey,
  19. AfterKey,
  20. BeforeValue,
  21. AfterValue,
  22. End,
  23. }
  24. // Properties
  25. private Dictionary<string, object> value;
  26. // ================================================================================================================
  27. // CONSTRUCTOR ----------------------------------------------------------------------------------------------------
  28. public JSONObject() : base() {
  29. }
  30. public JSONObject(object value) : base(value) {
  31. }
  32. public JSONObject(StringBuilder input, int position) : base(input, position) {
  33. }
  34. // ================================================================================================================
  35. // PUBLIC INTERFACE -----------------------------------------------------------------------------------------------
  36. public static bool matchesInput(StringBuilder input, int position) {
  37. return JSONParser.compareStringValue(CHAR_START.ToString(), input, position + JSONParser.countWhitespaceCharacters(input, position));
  38. }
  39. public static bool matchesValue(object value) {
  40. // TODO: this will always return true?
  41. return !value.GetType().IsPrimitive;
  42. }
  43. public override object getValue() {
  44. return value;
  45. }
  46. public override void setValue(object newValue) {
  47. value = (Dictionary<string, object>)newValue;
  48. }
  49. // ================================================================================================================
  50. // INTERNAL INTERFACE ---------------------------------------------------------------------------------------------
  51. protected override void parseValueFromInput() {
  52. ParsingState parsingState = ParsingState.Start;
  53. char c;
  54. int i = 0;
  55. string key = "undefined";
  56. JSONValue valueObject;
  57. value = new Dictionary<string, object>();
  58. while (i < input.Length && parsingState != ParsingState.End) {
  59. c = input.ToString(inputStart + i, 1)[0]; // TODO: is this efficient?
  60. switch (parsingState) {
  61. case ParsingState.Start:
  62. if (c == CHAR_START) {
  63. // Starting object
  64. parsingState = ParsingState.BeforeKey;
  65. } else {
  66. Debug.LogError("Invalid character \"" + c + "\" when expecting object key start");
  67. }
  68. break;
  69. case ParsingState.BeforeKey:
  70. if (!JSONParser.isWhitespace(c)) {
  71. if (JSONString.matchesInput(input, inputStart + i)) {
  72. // Key starting
  73. JSONString keyObject = new JSONString(input, inputStart + i);
  74. key = (string) keyObject.getValue();
  75. i += keyObject.getInputLength() - 1;
  76. parsingState = ParsingState.AfterKey;
  77. } else if (c == CHAR_END) {
  78. // Premature end
  79. parsingState = ParsingState.End;
  80. } else {
  81. Debug.LogError("Invalid character \"" + c + "\" when expecting object key name");
  82. }
  83. }
  84. break;
  85. case ParsingState.AfterKey:
  86. if (!JSONParser.isWhitespace(c)) {
  87. if (c == CHAR_KEY_SEPARATOR) {
  88. parsingState = ParsingState.BeforeValue;
  89. } else {
  90. Debug.LogError("Invalid character \"" + c + "\" when expecting object key separator");
  91. }
  92. }
  93. break;
  94. case ParsingState.BeforeValue:
  95. if (!JSONParser.isWhitespace(c)) {
  96. valueObject = JSONParser.parse(input, inputStart + i);
  97. i += valueObject.getInputLength() - 1;
  98. value.Add(key, valueObject.getValue());
  99. parsingState = ParsingState.AfterValue;
  100. }
  101. break;
  102. case ParsingState.AfterValue:
  103. if (!JSONParser.isWhitespace(c)) {
  104. if (c == CHAR_END) {
  105. parsingState = ParsingState.End;
  106. } else if (c == CHAR_ITEM_SEPARATOR) {
  107. parsingState = ParsingState.BeforeKey;
  108. } else {
  109. Debug.LogError("Invalid character \"" + c + "\" when expecting object key end");
  110. }
  111. }
  112. break;
  113. }
  114. i++;
  115. }
  116. inputLength = i;
  117. }
  118. protected override string stringifyValue(int indentLevel, JSONStringifyOptions options) {
  119. var t = new StringBuilder();
  120. bool hasItemsInList = false;
  121. t.Append(CHAR_START);
  122. foreach(KeyValuePair<string, object> valueItem in value) {
  123. if (hasItemsInList) t.Append(CHAR_ITEM_SEPARATOR);
  124. t.Append(options.lineFeed + JSONEncoder.getIndents(options.individualIndent, indentLevel + 1));
  125. t.Append(JSONEncoder.encode(valueItem.Key, 0, options));
  126. t.Append(options.objectAfterKey + CHAR_KEY_SEPARATOR + options.objectBeforeValue);
  127. t.Append(JSONEncoder.encode(valueItem.Value, indentLevel + 1, options));
  128. hasItemsInList = true;
  129. }
  130. t.Append(options.lineFeed + JSONEncoder.getIndents(options.individualIndent, indentLevel));
  131. t.Append(CHAR_END);
  132. return t.ToString();
  133. }
  134. }