UnityMol  0.9.6-875
UnityMol viewer / In developement
MiniJSON.cs
Go to the documentation of this file.
1 
66 // using UnityEngine;
67 using System;
68 using System.Collections;
69 using System.Text;
70 using UnityEngine;
71 /* Based on the JSON parser from
72  * http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html
73  *
74  * I simplified it so that it doesn't throw exceptions
75  * and can be used in Unity iPhone with maximum code stripping.
76  */
84 public class MiniJSON
85 {
86  public const int TOKEN_NONE = 0;
87  public const int TOKEN_CURLY_OPEN = 1;
88  public const int TOKEN_CURLY_CLOSE = 2;
89  public const int TOKEN_SQUARED_OPEN = 3;
90  public const int TOKEN_SQUARED_CLOSE = 4;
91  public const int TOKEN_COLON = 5;
92  public const int TOKEN_COMMA = 6;
93  public const int TOKEN_STRING = 7;
94  public const int TOKEN_NUMBER = 8;
95  public const int TOKEN_TRUE = 9;
96  public const int TOKEN_FALSE = 10;
97  public const int TOKEN_NULL = 11;
98 
99  private const int BUILDER_CAPACITY = 2000;
100 
101  protected static MiniJSON instance = new MiniJSON();
102 
106  protected int lastErrorIndex = -1;
107  protected string lastDecode = "";
108 
114  public static object JsonDecode(string json)
115  {
116  // save the string for debug information
118 
119  if (json != null)
120  {
121  char[] charArray = json.ToCharArray();
122 // for(int jj=charArray.Length-20;jj<charArray.Length;jj++)
123 // {
124 // Debug.Log(charArray[jj]);
125 // }
126 
127  int index = 0;
128  bool success = true;
129  object value = MiniJSON.instance.ParseValue(charArray, ref index, ref success);
130  //Hashtable FieldLines = (Hashtable)value ;
131  Debug.Log("object value =");
132 
133  if (success)
134  {
136  }
137  else
138  {
140  }
141 // Debug.Log((string)value);
142  return value;
143  }
144  else
145  {
146  return null;
147  }
148  }
149 
155  public static string JsonEncode(object json)
156  {
157  StringBuilder builder = new StringBuilder(BUILDER_CAPACITY);
158  bool success = MiniJSON.instance.SerializeValue(json, builder);
159  return (success ? builder.ToString() : null);
160  }
161 
166  public static bool LastDecodeSuccessful()
167  {
168  return (MiniJSON.instance.lastErrorIndex == -1);
169  }
170 
175  public static int GetLastErrorIndex()
176  {
178  }
179 
185  public static string GetLastErrorSnippet()
186  {
187  if (MiniJSON.instance.lastErrorIndex == -1) {
188  return "";
189  } else {
190  int startIndex = MiniJSON.instance.lastErrorIndex - 5;
191  int endIndex = MiniJSON.instance.lastErrorIndex + 15;
192  if (startIndex < 0) {
193  startIndex = 0;
194  }
195  if (endIndex >= MiniJSON.instance.lastDecode.Length) {
196  endIndex = MiniJSON.instance.lastDecode.Length - 1;
197  }
198 
199  return MiniJSON.instance.lastDecode.Substring(startIndex, endIndex - startIndex + 1);
200  }
201  }
202 
203  protected Hashtable ParseObject(char[] json, ref int index)
204  {
205  Hashtable table = new Hashtable();
206  int token;
207 
208  // {
209  NextToken(json, ref index);
210 
211  bool done = false;
212  while (!done) {
213  token = LookAhead(json, index);
214  if (token == MiniJSON.TOKEN_NONE) {
215  return null;
216  } else if (token == MiniJSON.TOKEN_COMMA) {
217  NextToken(json, ref index);
218  } else if (token == MiniJSON.TOKEN_CURLY_CLOSE) {
219  NextToken(json, ref index);
220  return table;
221  } else {
222 
223  // name
224  string name = ParseString(json, ref index);
225  if (name == null) {
226  return null;
227  }
228 
229  // :
230  token = NextToken(json, ref index);
231  if (token != MiniJSON.TOKEN_COLON) {
232  return null;
233  }
234 
235  // value
236  bool success = true;
237  object value = ParseValue(json, ref index, ref success);
238  if (!success) {
239  return null;
240  }
241 
242  table[name] = value;
243  }
244  }
245 
246  return table;
247  }
248 
249  protected ArrayList ParseArray(char[] json, ref int index)
250  {
251  ArrayList array = new ArrayList();
252 
253  // [
254  NextToken(json, ref index);
255 
256  bool done = false;
257  while (!done) {
258  int token = LookAhead(json, index);
259  if (token == MiniJSON.TOKEN_NONE) {
260  return null;
261  } else if (token == MiniJSON.TOKEN_COMMA) {
262  NextToken(json, ref index);
263  } else if (token == MiniJSON.TOKEN_SQUARED_CLOSE) {
264  NextToken(json, ref index);
265  break;
266  } else {
267  bool success = true;
268  object value = ParseValue(json, ref index, ref success);
269  if (!success) {
270  return null;
271  }
272 
273  array.Add(value);
274  }
275  }
276 
277  return array;
278  }
279 
280  protected object ParseValue(char[] json, ref int index, ref bool success)
281  {
282  switch (LookAhead(json, index)) {
283  case MiniJSON.TOKEN_STRING:
284 // Debug.Log("TOKEN_STRING");
285  return ParseString(json, ref index);
286  case MiniJSON.TOKEN_NUMBER:
287 // Debug.Log("TOKEN_NUMBER");
288  return ParseNumber(json, ref index);
290 // Debug.Log("TOKEN_CURLY_OPEN");
291  return ParseObject(json, ref index);
293 // Debug.Log("TOKEN_SQUARED_OPEN");
294  return ParseArray(json, ref index);
295  case MiniJSON.TOKEN_TRUE:
296 // Debug.Log("TOKEN_TRUE");
297  NextToken(json, ref index);
298  return Boolean.Parse("TRUE");
299  case MiniJSON.TOKEN_FALSE:
300 // Debug.Log("TOKEN_FALSE");
301  NextToken(json, ref index);
302  return Boolean.Parse("FALSE");
303  case MiniJSON.TOKEN_NULL:
304 // Debug.Log("TOKEN_NULL");
305  NextToken(json, ref index);
306  return null;
307  case MiniJSON.TOKEN_NONE:
308 // Debug.Log("TOKEN_NONE");
309  break;
310  }
311 
312  success = false;
313  return null;
314  }
315 
316  protected string ParseString(char[] json, ref int index)
317  {
318  string s = "";
319  char c;
320 
321  EatWhitespace(json, ref index);
322 
323  // "
324  c = json[index++];
325 
326  bool complete = false;
327  while (!complete) {
328 
329  if (index == json.Length) {
330  break;
331  }
332 
333  c = json[index++];
334  if (c == '"') {
335  complete = true;
336  break;
337  } else if (c == '\\') {
338 
339  if (index == json.Length) {
340  break;
341  }
342  c = json[index++];
343  if (c == '"') {
344  s += '"';
345  } else if (c == '\\') {
346  s += '\\';
347  } else if (c == '/') {
348  s += '/';
349  } else if (c == 'b') {
350  s += '\b';
351  } else if (c == 'f') {
352  s += '\f';
353  } else if (c == 'n') {
354  s += '\n';
355  } else if (c == 'r') {
356  s += '\r';
357  } else if (c == 't') {
358  s += '\t';
359  } else if (c == 'u') {
360  int remainingLength = json.Length - index;
361  if (remainingLength >= 4) {
362  char[] unicodeCharArray = new char[4];
363  Array.Copy(json, index, unicodeCharArray, 0, 4);
364 
365  // Drop in the HTML markup for the unicode character
366  s += "&#x" + new string(unicodeCharArray) + ";";
367 
368  /*
369  uint codePoint = UInt32.Parse(new string(unicodeCharArray), NumberStyles.HexNumber);
370  // convert the integer codepoint to a unicode char and add to string
371  s += Char.ConvertFromUtf32((int)codePoint);
372  */
373 
374  // skip 4 chars
375  index += 4;
376  } else {
377  break;
378  }
379  }
380  } else {
381  s += c;
382  }
383 
384  }
385 
386  if (!complete) {
387  return null;
388  }
389 
390  return s;
391  }
392 
393  protected double ParseNumber(char[] json, ref int index)
394  {
395  EatWhitespace(json, ref index);
396 
397  int lastIndex = GetLastIndexOfNumber(json, index);
398  int charLength = (lastIndex - index) + 1;
399  char[] numberCharArray = new char[charLength];
400 
401  Array.Copy(json, index, numberCharArray, 0, charLength);
402  index = lastIndex + 1;
403  return Double.Parse(new string(numberCharArray)); // , CultureInfo.InvariantCulture);
404  }
405 
406  protected int GetLastIndexOfNumber(char[] json, int index)
407  {
408  int lastIndex;
409  for (lastIndex = index; lastIndex < json.Length; lastIndex++) {
410  if ("0123456789+-.eE".IndexOf(json[lastIndex]) == -1) {
411  break;
412  }
413  }
414  return lastIndex - 1;
415  }
416 
417  protected void EatWhitespace(char[] json, ref int index)
418  {
419  for (; index < json.Length; index++) {
420  if (" \t\n\r".IndexOf(json[index]) == -1) {
421  break;
422  }
423  }
424  }
425 
426  protected int LookAhead(char[] json, int index)
427  {
428  int saveIndex = index;
429  return NextToken(json, ref saveIndex);
430  }
431 
432  protected int NextToken(char[] json, ref int index)
433  {
434  EatWhitespace(json, ref index);
435 
436  if (index == json.Length) {
437  return MiniJSON.TOKEN_NONE;
438  }
439 
440  char c = json[index];
441  index++;
442  switch (c) {
443  case '{':
444  return MiniJSON.TOKEN_CURLY_OPEN;
445  case '}':
447  case '[':
449  case ']':
451  case ',':
452  return MiniJSON.TOKEN_COMMA;
453  case '"':
454  return MiniJSON.TOKEN_STRING;
455  case '0': case '1': case '2': case '3': case '4':
456  case '5': case '6': case '7': case '8': case '9':
457  case '-':
458  return MiniJSON.TOKEN_NUMBER;
459  case ':':
460  return MiniJSON.TOKEN_COLON;
461  }
462  index--;
463 
464  int remainingLength = json.Length - index;
465 
466  // false
467  if (remainingLength >= 5) {
468  if (json[index] == 'f' &&
469  json[index + 1] == 'a' &&
470  json[index + 2] == 'l' &&
471  json[index + 3] == 's' &&
472  json[index + 4] == 'e') {
473  index += 5;
474  return MiniJSON.TOKEN_FALSE;
475  }
476  }
477 
478  // true
479  if (remainingLength >= 4) {
480  if (json[index] == 't' &&
481  json[index + 1] == 'r' &&
482  json[index + 2] == 'u' &&
483  json[index + 3] == 'e') {
484  index += 4;
485  return MiniJSON.TOKEN_TRUE;
486  }
487  }
488 
489  // null
490  if (remainingLength >= 4) {
491  if (json[index] == 'n' &&
492  json[index + 1] == 'u' &&
493  json[index + 2] == 'l' &&
494  json[index + 3] == 'l') {
495  index += 4;
496  return MiniJSON.TOKEN_NULL;
497  }
498  }
499 
500  return MiniJSON.TOKEN_NONE;
501  }
502 
503  protected bool SerializeObjectOrArray(object objectOrArray, StringBuilder builder)
504  {
505  if (objectOrArray is Hashtable) {
506  return SerializeObject((Hashtable)objectOrArray, builder);
507  } else if (objectOrArray is ArrayList) {
508  return SerializeArray((ArrayList)objectOrArray, builder);
509  } else {
510  return false;
511  }
512  }
513 
514  protected bool SerializeObject(Hashtable anObject, StringBuilder builder)
515  {
516  builder.Append("{");
517 
518  IDictionaryEnumerator e = anObject.GetEnumerator();
519  bool first = true;
520  while (e.MoveNext()) {
521  string key = e.Key.ToString();
522  object value = e.Value;
523 
524  if (!first) {
525  builder.Append(", ");
526  }
527 
528  SerializeString(key, builder);
529  builder.Append(":");
530  if (!SerializeValue(value, builder)) {
531  return false;
532  }
533 
534  first = false;
535  }
536 
537  builder.Append("}");
538  return true;
539  }
540 
541  protected bool SerializeArray(ArrayList anArray, StringBuilder builder)
542  {
543  builder.Append("[");
544 
545  bool first = true;
546  for (int i = 0; i < anArray.Count; i++) {
547  object value = anArray[i];
548 
549  if (!first) {
550  builder.Append(", ");
551  }
552 
553  if (!SerializeValue(value, builder)) {
554  return false;
555  }
556 
557  first = false;
558  }
559 
560  builder.Append("]");
561  return true;
562  }
563 
564  protected bool SerializeValue(object value, StringBuilder builder)
565  {
566 
567  // Type t = value.GetType();
568 
569  // Debug.Log("type: " + t.ToString() + " isArray: " + t.IsArray);
570 
571  if (value.GetType().IsArray) {
572  SerializeArray(new ArrayList((ICollection) value), builder);
573  } else if (value is string) {
574  SerializeString((string)value, builder);
575  } else if (value is Char) {
576  SerializeString(System.Convert.ToString((char) value), builder);
577  } else if (value is Hashtable) {
578  SerializeObject((Hashtable)value, builder);
579  } else if (value is ArrayList) {
580  SerializeArray((ArrayList)value, builder);
581  }
582  else if ((value is Boolean) && ((Boolean)value == true)) {
583  builder.Append("true");
584  } else if ((value is Boolean) && ((Boolean)value == false)) {
585  builder.Append("false");
586  }
587  else if (value.GetType().IsPrimitive) {
588  SerializeNumber(System.Convert.ToDouble(value), builder);
589  } else if (value == null) {
590  builder.Append("null");
591  } else {
592  return false;
593  }
594  return true;
595  }
596 
597  protected void SerializeString(string aString, StringBuilder builder)
598  {
599  builder.Append("\"");
600 
601  char[] charArray = aString.ToCharArray();
602  for (int i = 0; i < charArray.Length; i++) {
603  char c = charArray[i];
604  if (c == '"') {
605  builder.Append("\\\"");
606  } else if (c == '\\') {
607  builder.Append("\\\\");
608  } else if (c == '\b') {
609  builder.Append("\\b");
610  } else if (c == '\f') {
611  builder.Append("\\f");
612  } else if (c == '\n') {
613  builder.Append("\\n");
614  } else if (c == '\r') {
615  builder.Append("\\r");
616  } else if (c == '\t') {
617  builder.Append("\\t");
618  } else {
619  int codepoint = System.Convert.ToInt32(c);
620  if ((codepoint >= 32) && (codepoint <= 126)) {
621  builder.Append(c);
622  } else {
623  builder.Append("\\u" + System.Convert.ToString(codepoint, 16).PadLeft(4, '0'));
624  }
625  }
626  }
627 
628  builder.Append("\"");
629  }
630 
631  protected void SerializeNumber(double number, StringBuilder builder)
632  {
633  builder.Append(System.Convert.ToString(number)); // , CultureInfo.InvariantCulture));
634  }
635 
636  /*
641  protected bool IsNumeric(object o)
642  {
643  try {
644  Double.Parse(o.ToString());
645  } catch (Exception e) {
646  // Something went wrong, so lets get information about it.
647  Debug.Log(e.ToString());
648  return false;
649  }
650  return true;
651  }
652  */
653 }
static string JsonEncode(object json)
Converts a Hashtable / ArrayList object into a JSON string
Definition: MiniJSON.cs:155
double ParseNumber(char[] json, ref int index)
Definition: MiniJSON.cs:393
const int TOKEN_NUMBER
Definition: MiniJSON.cs:94
string ParseString(char[] json, ref int index)
Definition: MiniJSON.cs:316
ArrayList ParseArray(char[] json, ref int index)
Definition: MiniJSON.cs:249
const int TOKEN_SQUARED_CLOSE
Definition: MiniJSON.cs:90
int NextToken(char[] json, ref int index)
Definition: MiniJSON.cs:432
void SerializeNumber(double number, StringBuilder builder)
Definition: MiniJSON.cs:631
const int TOKEN_CURLY_CLOSE
Definition: MiniJSON.cs:88
const int TOKEN_COMMA
Definition: MiniJSON.cs:92
Hashtable ParseObject(char[] json, ref int index)
Definition: MiniJSON.cs:203
static string GetLastErrorSnippet()
If a decoding error occurred, this function returns a piece of the JSON string at which the error too...
Definition: MiniJSON.cs:185
static MiniJSON instance
Definition: MiniJSON.cs:101
bool SerializeObject(Hashtable anObject, StringBuilder builder)
Definition: MiniJSON.cs:514
This class encodes and decodes JSON strings.
Definition: MiniJSON.cs:84
const int TOKEN_SQUARED_OPEN
Definition: MiniJSON.cs:89
const int TOKEN_FALSE
Definition: MiniJSON.cs:96
const int TOKEN_STRING
Definition: MiniJSON.cs:93
bool SerializeValue(object value, StringBuilder builder)
Definition: MiniJSON.cs:564
static bool LastDecodeSuccessful()
On decoding, this function returns the position at which the parse failed (-1 = no error)...
Definition: MiniJSON.cs:166
static object JsonDecode(string json)
Parses the string json into a value
Definition: MiniJSON.cs:114
void SerializeString(string aString, StringBuilder builder)
Definition: MiniJSON.cs:597
const int BUILDER_CAPACITY
Definition: MiniJSON.cs:99
const int TOKEN_NONE
Definition: MiniJSON.cs:86
int LookAhead(char[] json, int index)
Definition: MiniJSON.cs:426
string lastDecode
Definition: MiniJSON.cs:107
static int GetLastErrorIndex()
On decoding, this function returns the position at which the parse failed (-1 = no error)...
Definition: MiniJSON.cs:175
bool SerializeArray(ArrayList anArray, StringBuilder builder)
Definition: MiniJSON.cs:541
bool SerializeObjectOrArray(object objectOrArray, StringBuilder builder)
Definition: MiniJSON.cs:503
const int TOKEN_CURLY_OPEN
Definition: MiniJSON.cs:87
const int TOKEN_TRUE
Definition: MiniJSON.cs:95
const int TOKEN_NULL
Definition: MiniJSON.cs:97
object ParseValue(char[] json, ref int index, ref bool success)
Definition: MiniJSON.cs:280
int lastErrorIndex
On decoding, this value holds the position at which the parse failed (-1 = no error).
Definition: MiniJSON.cs:106
const int TOKEN_COLON
Definition: MiniJSON.cs:91
void EatWhitespace(char[] json, ref int index)
Definition: MiniJSON.cs:417
int GetLastIndexOfNumber(char[] json, int index)
Definition: MiniJSON.cs:406