Statistics
| Branch: | Tag: | Revision:

root / Assets / Plugins / LitJson / JsonData.cs @ 11:01dde4258840

History | View | Annotate | Download (24.5 kB)

1
#region Header
2
/**
3
 * JsonData.cs
4
 *   Generic type to hold JSON data (objects, arrays, and so on). This is
5
 *   the default type returned by JsonMapper.ToObject().
6
 *
7
 * The authors disclaim copyright to this source code. For more details, see
8
 * the COPYING file included with this distribution.
9
 **/
10
#endregion
11
12
13
using System;
14
using System.Collections;
15
using System.Collections.Generic;
16
using System.Collections.Specialized;
17
using System.IO;
18
19
20
namespace LitJson
21
{
22
    public class JsonData : IJsonWrapper, IEquatable<JsonData>
23
    {
24
        #region Fields
25
        private IList<JsonData>               inst_array;
26
        private bool                          inst_boolean;
27
        private double                        inst_double;
28
        private int                           inst_int;
29
        private long                          inst_long;
30
        private IDictionary<string, JsonData> inst_object;
31
        private string                        inst_string;
32
        private string                        json;
33
        private JsonType                      type;
34
35
        // Used to implement the IOrderedDictionary interface
36
        private IList<KeyValuePair<string, JsonData>> object_list;
37
        #endregion
38
39
40
        #region Properties
41
        public int Count {
42
            get { return EnsureCollection ().Count; }
43
        }
44
45
        public bool IsArray {
46
            get { return type == JsonType.Array; }
47
        }
48
49
        public bool IsBoolean {
50
            get { return type == JsonType.Boolean; }
51
        }
52
53
        public bool IsDouble {
54
            get { return type == JsonType.Double; }
55
        }
56
57
        public bool IsInt {
58
            get { return type == JsonType.Int; }
59
        }
60
61
        public bool IsLong {
62
            get { return type == JsonType.Long; }
63
        }
64
65
        public bool IsObject {
66
            get { return type == JsonType.Object; }
67
        }
68
69
        public bool IsString {
70
            get { return type == JsonType.String; }
71
        }
72
        #endregion
73
74
75
        #region ICollection Properties
76
        int ICollection.Count {
77
            get {
78
                return Count;
79
            }
80
        }
81
82
        bool ICollection.IsSynchronized {
83
            get {
84
                return EnsureCollection ().IsSynchronized;
85
            }
86
        }
87
88
        object ICollection.SyncRoot {
89
            get {
90
                return EnsureCollection ().SyncRoot;
91
            }
92
        }
93
        #endregion
94
95
96
        #region IDictionary Properties
97
        bool IDictionary.IsFixedSize {
98
            get {
99
                return EnsureDictionary ().IsFixedSize;
100
            }
101
        }
102
103
        bool IDictionary.IsReadOnly {
104
            get {
105
                return EnsureDictionary ().IsReadOnly;
106
            }
107
        }
108
109
        ICollection IDictionary.Keys {
110
            get {
111
                EnsureDictionary ();
112
                IList<string> keys = new List<string> ();
113
114
                foreach (KeyValuePair<string, JsonData> entry in
115
                         object_list) {
116
                    keys.Add (entry.Key);
117
                }
118
119
                return (ICollection) keys;
120
            }
121
        }
122
123
        ICollection IDictionary.Values {
124
            get {
125
                EnsureDictionary ();
126
                IList<JsonData> values = new List<JsonData> ();
127
128
                foreach (KeyValuePair<string, JsonData> entry in
129
                         object_list) {
130
                    values.Add (entry.Value);
131
                }
132
133
                return (ICollection) values;
134
            }
135
        }
136
        #endregion
137
138
139
140
        #region IJsonWrapper Properties
141
        bool IJsonWrapper.IsArray {
142
            get { return IsArray; }
143
        }
144
145
        bool IJsonWrapper.IsBoolean {
146
            get { return IsBoolean; }
147
        }
148
149
        bool IJsonWrapper.IsDouble {
150
            get { return IsDouble; }
151
        }
152
153
        bool IJsonWrapper.IsInt {
154
            get { return IsInt; }
155
        }
156
157
        bool IJsonWrapper.IsLong {
158
            get { return IsLong; }
159
        }
160
161
        bool IJsonWrapper.IsObject {
162
            get { return IsObject; }
163
        }
164
165
        bool IJsonWrapper.IsString {
166
            get { return IsString; }
167
        }
168
        #endregion
169
170
171
        #region IList Properties
172
        bool IList.IsFixedSize {
173
            get {
174
                return EnsureList ().IsFixedSize;
175
            }
176
        }
177
178
        bool IList.IsReadOnly {
179
            get {
180
                return EnsureList ().IsReadOnly;
181
            }
182
        }
183
        #endregion
184
185
186
        #region IDictionary Indexer
187
        object IDictionary.this[object key] {
188
            get {
189
                return EnsureDictionary ()[key];
190
            }
191
192
            set {
193
                if (! (key is String))
194
                    throw new ArgumentException (
195
                        "The key has to be a string");
196
197
                JsonData data = ToJsonData (value);
198
199
                this[(string) key] = data;
200
            }
201
        }
202
        #endregion
203
204
205
        #region IOrderedDictionary Indexer
206
        object IOrderedDictionary.this[int idx] {
207
            get {
208
                EnsureDictionary ();
209
                return object_list[idx].Value;
210
            }
211
212
            set {
213
                EnsureDictionary ();
214
                JsonData data = ToJsonData (value);
215
216
                KeyValuePair<string, JsonData> old_entry = object_list[idx];
217
218
                inst_object[old_entry.Key] = data;
219
220
                KeyValuePair<string, JsonData> entry =
221
                    new KeyValuePair<string, JsonData> (old_entry.Key, data);
222
223
                object_list[idx] = entry;
224
            }
225
        }
226
        #endregion
227
228
229
        #region IList Indexer
230
        object IList.this[int index] {
231
            get {
232
                return EnsureList ()[index];
233
            }
234
235
            set {
236
                EnsureList ();
237
                JsonData data = ToJsonData (value);
238
239
                this[index] = data;
240
            }
241
        }
242
        #endregion
243
244
245
        #region Public Indexers
246
        public JsonData this[string prop_name] {
247
            get {
248
                EnsureDictionary ();
249
                return inst_object[prop_name];
250
            }
251
252
            set {
253
                EnsureDictionary ();
254
255
                KeyValuePair<string, JsonData> entry =
256
                    new KeyValuePair<string, JsonData> (prop_name, value);
257
258
                if (inst_object.ContainsKey (prop_name)) {
259
                    for (int i = 0; i < object_list.Count; i++) {
260
                        if (object_list[i].Key == prop_name) {
261
                            object_list[i] = entry;
262
                            break;
263
                        }
264
                    }
265
                } else
266
                    object_list.Add (entry);
267
268
                inst_object[prop_name] = value;
269
270
                json = null;
271
            }
272
        }
273
274
        public JsonData this[int index] {
275
            get {
276
                EnsureCollection ();
277
278
                if (type == JsonType.Array)
279
                    return inst_array[index];
280
281
                return object_list[index].Value;
282
            }
283
284
            set {
285
                EnsureCollection ();
286
287
                if (type == JsonType.Array)
288
                    inst_array[index] = value;
289
                else {
290
                    KeyValuePair<string, JsonData> entry = object_list[index];
291
                    KeyValuePair<string, JsonData> new_entry =
292
                        new KeyValuePair<string, JsonData> (entry.Key, value);
293
294
                    object_list[index] = new_entry;
295
                    inst_object[entry.Key] = value;
296
                }
297
298
                json = null;
299
            }
300
        }
301
        #endregion
302
303
304
        #region Constructors
305
        public JsonData ()
306
        {
307
        }
308
309
        public JsonData (bool boolean)
310
        {
311
            type = JsonType.Boolean;
312
            inst_boolean = boolean;
313
        }
314
315
        public JsonData (double number)
316
        {
317
            type = JsonType.Double;
318
            inst_double = number;
319
        }
320
321
        public JsonData (int number)
322
        {
323
            type = JsonType.Int;
324
            inst_int = number;
325
        }
326
327
        public JsonData (long number)
328
        {
329
            type = JsonType.Long;
330
            inst_long = number;
331
        }
332
333
        public JsonData (object obj)
334
        {
335
            if (obj is Boolean) {
336
                type = JsonType.Boolean;
337
                inst_boolean = (bool) obj;
338
                return;
339
            }
340
341
            if (obj is Double) {
342
                type = JsonType.Double;
343
                inst_double = (double) obj;
344
                return;
345
            }
346
347
            if (obj is Int32) {
348
                type = JsonType.Int;
349
                inst_int = (int) obj;
350
                return;
351
            }
352
353
            if (obj is Int64) {
354
                type = JsonType.Long;
355
                inst_long = (long) obj;
356
                return;
357
            }
358
359
            if (obj is String) {
360
                type = JsonType.String;
361
                inst_string = (string) obj;
362
                return;
363
            }
364
365
            throw new ArgumentException (
366
                "Unable to wrap the given object with JsonData");
367
        }
368
369
        public JsonData (string str)
370
        {
371
            type = JsonType.String;
372
            inst_string = str;
373
        }
374
        #endregion
375
376
377
        #region Implicit Conversions
378
        public static implicit operator JsonData (Boolean data)
379
        {
380
            return new JsonData (data);
381
        }
382
383
        public static implicit operator JsonData (Double data)
384
        {
385
            return new JsonData (data);
386
        }
387
388
        public static implicit operator JsonData (Int32 data)
389
        {
390
            return new JsonData (data);
391
        }
392
393
        public static implicit operator JsonData (Int64 data)
394
        {
395
            return new JsonData (data);
396
        }
397
398
        public static implicit operator JsonData (String data)
399
        {
400
            return new JsonData (data);
401
        }
402
        #endregion
403
404
405
        #region Explicit Conversions
406
        public static explicit operator Boolean (JsonData data)
407
        {
408
            if (data.type != JsonType.Boolean)
409
                throw new InvalidCastException (
410
                    "Instance of JsonData doesn't hold a double");
411
412
            return data.inst_boolean;
413
        }
414
415
        public static explicit operator Double (JsonData data)
416
        {
417
            if (data.type != JsonType.Double)
418
                throw new InvalidCastException (
419
                    "Instance of JsonData doesn't hold a double");
420
421
            return data.inst_double;
422
        }
423
424
        public static explicit operator Int32 (JsonData data)
425
        {
426
            if (data.type != JsonType.Int)
427
                throw new InvalidCastException (
428
                    "Instance of JsonData doesn't hold an int");
429
430
            return data.inst_int;
431
        }
432
433
        public static explicit operator Int64 (JsonData data)
434
        {
435
            if (data.type != JsonType.Long)
436
                throw new InvalidCastException (
437
                    "Instance of JsonData doesn't hold an int");
438
439
            return data.inst_long;
440
        }
441
442
        public static explicit operator String (JsonData data)
443
        {
444
            if (data.type != JsonType.String)
445
                throw new InvalidCastException (
446
                    "Instance of JsonData doesn't hold a string");
447
448
            return data.inst_string;
449
        }
450
        #endregion
451
452
453
        #region ICollection Methods
454
        void ICollection.CopyTo (Array array, int index)
455
        {
456
            EnsureCollection ().CopyTo (array, index);
457
        }
458
        #endregion
459
460
461
        #region IDictionary Methods
462
        void IDictionary.Add (object key, object value)
463
        {
464
            JsonData data = ToJsonData (value);
465
466
            EnsureDictionary ().Add (key, data);
467
468
            KeyValuePair<string, JsonData> entry =
469
                new KeyValuePair<string, JsonData> ((string) key, data);
470
            object_list.Add (entry);
471
472
            json = null;
473
        }
474
475
        void IDictionary.Clear ()
476
        {
477
            EnsureDictionary ().Clear ();
478
            object_list.Clear ();
479
            json = null;
480
        }
481
482
        bool IDictionary.Contains (object key)
483
        {
484
            return EnsureDictionary ().Contains (key);
485
        }
486
487
        IDictionaryEnumerator IDictionary.GetEnumerator ()
488
        {
489
            return ((IOrderedDictionary) this).GetEnumerator ();
490
        }
491
492
        void IDictionary.Remove (object key)
493
        {
494
            EnsureDictionary ().Remove (key);
495
496
            for (int i = 0; i < object_list.Count; i++) {
497
                if (object_list[i].Key == (string) key) {
498
                    object_list.RemoveAt (i);
499
                    break;
500
                }
501
            }
502
503
            json = null;
504
        }
505
        #endregion
506
507
508
        #region IEnumerable Methods
509
        IEnumerator IEnumerable.GetEnumerator ()
510
        {
511
            return EnsureCollection ().GetEnumerator ();
512
        }
513
        #endregion
514
515
516
        #region IJsonWrapper Methods
517
        bool IJsonWrapper.GetBoolean ()
518
        {
519
            if (type != JsonType.Boolean)
520
                throw new InvalidOperationException (
521
                    "JsonData instance doesn't hold a boolean");
522
523
            return inst_boolean;
524
        }
525
526
        double IJsonWrapper.GetDouble ()
527
        {
528
            if (type != JsonType.Double)
529
                throw new InvalidOperationException (
530
                    "JsonData instance doesn't hold a double");
531
532
            return inst_double;
533
        }
534
535
        int IJsonWrapper.GetInt ()
536
        {
537
            if (type != JsonType.Int)
538
                throw new InvalidOperationException (
539
                    "JsonData instance doesn't hold an int");
540
541
            return inst_int;
542
        }
543
544
        long IJsonWrapper.GetLong ()
545
        {
546
            if (type != JsonType.Long)
547
                throw new InvalidOperationException (
548
                    "JsonData instance doesn't hold a long");
549
550
            return inst_long;
551
        }
552
553
        string IJsonWrapper.GetString ()
554
        {
555
            if (type != JsonType.String)
556
                throw new InvalidOperationException (
557
                    "JsonData instance doesn't hold a string");
558
559
            return inst_string;
560
        }
561
562
        void IJsonWrapper.SetBoolean (bool val)
563
        {
564
            type = JsonType.Boolean;
565
            inst_boolean = val;
566
            json = null;
567
        }
568
569
        void IJsonWrapper.SetDouble (double val)
570
        {
571
            type = JsonType.Double;
572
            inst_double = val;
573
            json = null;
574
        }
575
576
        void IJsonWrapper.SetInt (int val)
577
        {
578
            type = JsonType.Int;
579
            inst_int = val;
580
            json = null;
581
        }
582
583
        void IJsonWrapper.SetLong (long val)
584
        {
585
            type = JsonType.Long;
586
            inst_long = val;
587
            json = null;
588
        }
589
590
        void IJsonWrapper.SetString (string val)
591
        {
592
            type = JsonType.String;
593
            inst_string = val;
594
            json = null;
595
        }
596
597
        string IJsonWrapper.ToJson ()
598
        {
599
            return ToJson ();
600
        }
601
602
        void IJsonWrapper.ToJson (JsonWriter writer)
603
        {
604
            ToJson (writer);
605
        }
606
        #endregion
607
608
609
        #region IList Methods
610
        int IList.Add (object value)
611
        {
612
            return Add (value);
613
        }
614
615
        void IList.Clear ()
616
        {
617
            EnsureList ().Clear ();
618
            json = null;
619
        }
620
621
        bool IList.Contains (object value)
622
        {
623
            return EnsureList ().Contains (value);
624
        }
625
626
        int IList.IndexOf (object value)
627
        {
628
            return EnsureList ().IndexOf (value);
629
        }
630
631
        void IList.Insert (int index, object value)
632
        {
633
            EnsureList ().Insert (index, value);
634
            json = null;
635
        }
636
637
        void IList.Remove (object value)
638
        {
639
            EnsureList ().Remove (value);
640
            json = null;
641
        }
642
643
        void IList.RemoveAt (int index)
644
        {
645
            EnsureList ().RemoveAt (index);
646
            json = null;
647
        }
648
        #endregion
649
650
651
        #region IOrderedDictionary Methods
652
        IDictionaryEnumerator IOrderedDictionary.GetEnumerator ()
653
        {
654
            EnsureDictionary ();
655
656
            return new OrderedDictionaryEnumerator (
657
                object_list.GetEnumerator ());
658
        }
659
660
        void IOrderedDictionary.Insert (int idx, object key, object value)
661
        {
662
            string property = (string) key;
663
            JsonData data  = ToJsonData (value);
664
665
            this[property] = data;
666
667
            KeyValuePair<string, JsonData> entry =
668
                new KeyValuePair<string, JsonData> (property, data);
669
670
            object_list.Insert (idx, entry);
671
        }
672
673
        void IOrderedDictionary.RemoveAt (int idx)
674
        {
675
            EnsureDictionary ();
676
677
            inst_object.Remove (object_list[idx].Key);
678
            object_list.RemoveAt (idx);
679
        }
680
        #endregion
681
682
683
        #region Private Methods
684
        private ICollection EnsureCollection ()
685
        {
686
            if (type == JsonType.Array)
687
                return (ICollection) inst_array;
688
689
            if (type == JsonType.Object)
690
                return (ICollection) inst_object;
691
692
            throw new InvalidOperationException (
693
                "The JsonData instance has to be initialized first");
694
        }
695
696
        private IDictionary EnsureDictionary ()
697
        {
698
            if (type == JsonType.Object)
699
                return (IDictionary) inst_object;
700
701
            if (type != JsonType.None)
702
                throw new InvalidOperationException (
703
                    "Instance of JsonData is not a dictionary");
704
705
            type = JsonType.Object;
706
            inst_object = new Dictionary<string, JsonData> ();
707
            object_list = new List<KeyValuePair<string, JsonData>> ();
708
709
            return (IDictionary) inst_object;
710
        }
711
712
        private IList EnsureList ()
713
        {
714
            if (type == JsonType.Array)
715
                return (IList) inst_array;
716
717
            if (type != JsonType.None)
718
                throw new InvalidOperationException (
719
                    "Instance of JsonData is not a list");
720
721
            type = JsonType.Array;
722
            inst_array = new List<JsonData> ();
723
724
            return (IList) inst_array;
725
        }
726
727
        private JsonData ToJsonData (object obj)
728
        {
729
            if (obj == null)
730
                return null;
731
732
            if (obj is JsonData)
733
                return (JsonData) obj;
734
735
            return new JsonData (obj);
736
        }
737
738
        private static void WriteJson (IJsonWrapper obj, JsonWriter writer)
739
        {
740
            if (obj == null) {
741
                writer.Write (null);
742
                return;
743
            }
744
745
            if (obj.IsString) {
746
                writer.Write (obj.GetString ());
747
                return;
748
            }
749
750
            if (obj.IsBoolean) {
751
                writer.Write (obj.GetBoolean ());
752
                return;
753
            }
754
755
            if (obj.IsDouble) {
756
                writer.Write (obj.GetDouble ());
757
                return;
758
            }
759
760
            if (obj.IsInt) {
761
                writer.Write (obj.GetInt ());
762
                return;
763
            }
764
765
            if (obj.IsLong) {
766
                writer.Write (obj.GetLong ());
767
                return;
768
            }
769
770
            if (obj.IsArray) {
771
                writer.WriteArrayStart ();
772
                foreach (object elem in (IList) obj)
773
                    WriteJson ((JsonData) elem, writer);
774
                writer.WriteArrayEnd ();
775
776
                return;
777
            }
778
779
            if (obj.IsObject) {
780
                writer.WriteObjectStart ();
781
782
                foreach (DictionaryEntry entry in ((IDictionary) obj)) {
783
                    writer.WritePropertyName ((string) entry.Key);
784
                    WriteJson ((JsonData) entry.Value, writer);
785
                }
786
                writer.WriteObjectEnd ();
787
788
                return;
789
            }
790
        }
791
        #endregion
792
793
794
        public int Add (object value)
795
        {
796
            JsonData data = ToJsonData (value);
797
798
            json = null;
799
800
            return EnsureList ().Add (data);
801
        }
802
803
        public void Clear ()
804
        {
805
            if (IsObject) {
806
                ((IDictionary) this).Clear ();
807
                return;
808
            }
809
810
            if (IsArray) {
811
                ((IList) this).Clear ();
812
                return;
813
            }
814
        }
815
816
        public bool Equals (JsonData x)
817
        {
818
            if (x == null)
819
                return false;
820
821
            if (x.type != this.type)
822
                return false;
823
824
            switch (this.type) {
825
            case JsonType.None:
826
                return true;
827
828
            case JsonType.Object:
829
                return this.inst_object.Equals (x.inst_object);
830
831
            case JsonType.Array:
832
                return this.inst_array.Equals (x.inst_array);
833
834
            case JsonType.String:
835
                return this.inst_string.Equals (x.inst_string);
836
837
            case JsonType.Int:
838
                return this.inst_int.Equals (x.inst_int);
839
840
            case JsonType.Long:
841
                return this.inst_long.Equals (x.inst_long);
842
843
            case JsonType.Double:
844
                return this.inst_double.Equals (x.inst_double);
845
846
            case JsonType.Boolean:
847
                return this.inst_boolean.Equals (x.inst_boolean);
848
            }
849
850
            return false;
851
        }
852
853
        public JsonType GetJsonType ()
854
        {
855
            return type;
856
        }
857
858
        public void SetJsonType (JsonType type)
859
        {
860
            if (this.type == type)
861
                return;
862
863
            switch (type) {
864
            case JsonType.None:
865
                break;
866
867
            case JsonType.Object:
868
                inst_object = new Dictionary<string, JsonData> ();
869
                object_list = new List<KeyValuePair<string, JsonData>> ();
870
                break;
871
872
            case JsonType.Array:
873
                inst_array = new List<JsonData> ();
874
                break;
875
876
            case JsonType.String:
877
                inst_string = default (String);
878
                break;
879
880
            case JsonType.Int:
881
                inst_int = default (Int32);
882
                break;
883
884
            case JsonType.Long:
885
                inst_long = default (Int64);
886
                break;
887
888
            case JsonType.Double:
889
                inst_double = default (Double);
890
                break;
891
892
            case JsonType.Boolean:
893
                inst_boolean = default (Boolean);
894
                break;
895
            }
896
897
            this.type = type;
898
        }
899
900
        public string ToJson ()
901
        {
902
            if (json != null)
903
                return json;
904
905
            StringWriter sw = new StringWriter ();
906
            JsonWriter writer = new JsonWriter (sw);
907
            writer.Validate = false;
908
909
            WriteJson (this, writer);
910
            json = sw.ToString ();
911
912
            return json;
913
        }
914
915
        public void ToJson (JsonWriter writer)
916
        {
917
            bool old_validate = writer.Validate;
918
919
            writer.Validate = false;
920
921
            WriteJson (this, writer);
922
923
            writer.Validate = old_validate;
924
        }
925
926
        public override string ToString ()
927
        {
928
            switch (type) {
929
            case JsonType.Array:
930
                return "JsonData array";
931
932
            case JsonType.Boolean:
933
                return inst_boolean.ToString ();
934
935
            case JsonType.Double:
936
                return inst_double.ToString ();
937
938
            case JsonType.Int:
939
                return inst_int.ToString ();
940
941
            case JsonType.Long:
942
                return inst_long.ToString ();
943
944
            case JsonType.Object:
945
                return "JsonData object";
946
947
            case JsonType.String:
948
                return inst_string;
949
            }
950
951
            return "Uninitialized JsonData";
952
        }
953
    }
954
955
956
    internal class OrderedDictionaryEnumerator : IDictionaryEnumerator
957
    {
958
        IEnumerator<KeyValuePair<string, JsonData>> list_enumerator;
959
960
961
        public object Current {
962
            get { return Entry; }
963
        }
964
965
        public DictionaryEntry Entry {
966
            get {
967
                KeyValuePair<string, JsonData> curr = list_enumerator.Current;
968
                return new DictionaryEntry (curr.Key, curr.Value);
969
            }
970
        }
971
972
        public object Key {
973
            get { return list_enumerator.Current.Key; }
974
        }
975
976
        public object Value {
977
            get { return list_enumerator.Current.Value; }
978
        }
979
980
981
        public OrderedDictionaryEnumerator (
982
            IEnumerator<KeyValuePair<string, JsonData>> enumerator)
983
        {
984
            list_enumerator = enumerator;
985
        }
986
987
988
        public bool MoveNext ()
989
        {
990
            return list_enumerator.MoveNext ();
991
        }
992
993
        public void Reset ()
994
        {
995
            list_enumerator.Reset ();
996
        }
997
    }
998
}