├── Consoletest ├── AssemblyInfo.cs ├── Program.cs ├── consoletest.csproj ├── dataobjects.cs └── mytests.cs ├── UnitTests.nunit ├── UnitTests ├── Properties │ └── AssemblyInfo.cs ├── Tests.cs └── UnitTests.csproj ├── fastBinaryJSON 3.5 └── fastBinaryJSON net35.csproj ├── fastBinaryJSON.nuspec ├── fastBinaryJSON.sln ├── fastBinaryJSON ├── AssemblyInfo.cs ├── BJSON.cs ├── BJsonParser.cs ├── BJsonSerializer.cs ├── Getters.cs ├── Reflection.cs ├── SafeDictionary.cs ├── dynamic.cs ├── fastBinaryJSON-android.csproj ├── fastBinaryJSON.csproj └── fastJSON.snk ├── fastBinaryJSONcore.sln ├── fastBinaryJSONcore ├── fastBinaryJSON.csproj └── fastBinaryJSON.snk ├── history.txt └── readme.md /Consoletest/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | #region Using directives 2 | 3 | using System.Reflection; 4 | using System.Runtime.InteropServices; 5 | 6 | #endregion 7 | 8 | // General Information about an assembly is controlled through the following 9 | // set of attributes. Change these attribute values to modify the information 10 | // associated with an assembly. 11 | [assembly: AssemblyTitle("consoletest")] 12 | [assembly: AssemblyDescription("")] 13 | [assembly: AssemblyConfiguration("")] 14 | [assembly: AssemblyCompany("")] 15 | [assembly: AssemblyProduct("consoletest")] 16 | [assembly: AssemblyCopyright("Copyright 2011")] 17 | [assembly: AssemblyTrademark("")] 18 | [assembly: AssemblyCulture("")] 19 | 20 | // This sets the default COM visibility of types in the assembly to invisible. 21 | // If you need to expose a type to COM, use [ComVisible(true)] on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | // The assembly version has following format : 25 | // 26 | // Major.Minor.Build.Revision 27 | // 28 | // You can specify all the values or you can use the default the Revision and 29 | // Build Numbers by using the '*' as shown below: 30 | [assembly: AssemblyVersion("1.0.*")] 31 | -------------------------------------------------------------------------------- /Consoletest/Program.cs: -------------------------------------------------------------------------------- 1 | using fastBinaryJSON; 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Data; 6 | using System.Diagnostics; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Runtime.Serialization.Formatters.Binary; 10 | 11 | namespace consoletest 12 | { 13 | public 14 | struct 15 | //class 16 | Return 17 | { 18 | public object ReturnEntity { get; set; } 19 | public string Name { get; set; } 20 | //public TimeSpan time { get; set; } 21 | public string Field1; 22 | public int Field2; 23 | public string ppp { get { return "sdfas df "; } } 24 | public DateTime date { get; set; } 25 | public DataTable ds { get; set; } 26 | public bool isValid { get; set; } 27 | } 28 | 29 | public class returns : List 30 | { 31 | public string name { get; set; } 32 | } 33 | 34 | public class NoExt 35 | { 36 | [System.Xml.Serialization.XmlIgnore()] 37 | public string Name { get; set; } 38 | public string Address { get; set;} 39 | public int Age { get; set;} 40 | public DateTime Date { get; set; } 41 | public baseclass[] objs { get; set;} 42 | public Dictionary dic { get; set; } 43 | } 44 | public class TestClass 45 | { 46 | public string Channel { get; set; } 47 | public string Start { get; set; } 48 | public string Stop { get; set; } 49 | public string Eventid { get; set; } 50 | public string Charset { get; set; } 51 | 52 | public List Titles { get; set; } = new List(); 53 | public List Events { get; set; } = new List(); 54 | public List Descriptions { get; set; } = new List(); 55 | 56 | public static List CreateList(int count) 57 | { 58 | List lst = new List(); 59 | foreach (int i in Enumerable.Range(1, count)) 60 | { 61 | TestClass t = new TestClass 62 | { 63 | Channel = $"Channel-{i % 10}", 64 | Start = $"{i * 1000}", 65 | Stop = $"{i * 1000 + 10}", 66 | Charset = "255" 67 | }; 68 | t.Descriptions.Add($"Description Description Description Description Description Description Description {i} "); 69 | t.Events.Add($"Event {i} "); 70 | t.Titles.Add($"The Title {i} "); 71 | lst.Add(t); 72 | } 73 | return lst; 74 | } 75 | } 76 | 77 | public class Program 78 | { 79 | static int count = 1000; 80 | static int tcount = 5; 81 | static DataSet ds = new DataSet(); 82 | static bool exotic = false; 83 | static bool dsser = false; 84 | 85 | public class test { } 86 | public static void Main(string[] args) 87 | { 88 | 89 | //fastbjson_deserialize(10); 90 | //return; 91 | // Return r = new Return(); 92 | // r.Name = "hello"; 93 | // r.Field1 = "dsasdF"; 94 | // r.Field2 = 2312; 95 | // r.date = DateTime.Now; 96 | // r.isValid = true; 97 | // r.ds = CreateDataset().Tables[0]; 98 | 99 | // r.ReturnEntity = 100 | // new List( new int[] { 1,2,3,4,5 }); 101 | // // // Guid.NewGuid(); 102 | // // // CreateDataset(); 103 | // // new object[] { new Return() }; 104 | // //r.time = new TimeSpan(1, 2, 3); 105 | // //r.point = new System.Drawing.Point(10, 10); 106 | 107 | // //rr.Add(r); 108 | 109 | // //fastJSON.JSON.RegisterCustomType(typeof(TimeSpan), tsser, tsdes); 110 | // //fastJSON.JSON.RegisterCustomType(typeof(System.Drawing.Point), pser, pdes); 111 | // //List list = new List(); 112 | // //list.Add("hello there"); 113 | // //list.Add(Guid.NewGuid()); 114 | // //list.Add(true); 115 | // //list.Add(null); 116 | // //list.Add(DateTime.Now); 117 | //// var ooo= fastBinaryJSON.BJSON.ToBJSON(list); 118 | //// var ppp = fastBinaryJSON.BJSON.ToObject(ooo); 119 | // byte[] ts = fastBinaryJSON.BJSON.ToBJSON(r); 120 | // object dic2 = fastBinaryJSON.BJSON.Parse(ts); 121 | // object tsd = fastBinaryJSON.BJSON.ToObject(ts); 122 | 123 | // NoExt ne = new NoExt(); 124 | // ne.Name = "hello"; 125 | // ne.Address = "here"; 126 | // ne.Age= 10; 127 | // ne.dic = new Dictionary(); 128 | // ne.dic.Add("hello", new class1("asda","asdas",Guid.NewGuid())); 129 | // ne.objs = new baseclass[] { new class1("a","1",Guid.NewGuid()), new class2("b","2","desc") }; 130 | 131 | // //fastJSON.JSON.UseSerializerExtension = false; 132 | // //fastJSON.JSON.UseFastGuid = false; 133 | // byte[] str = fastBinaryJSON.BJSON.ToBJSON(ne); 134 | // object dic = fastBinaryJSON.BJSON.Parse(str); 135 | // object oo = fastBinaryJSON.BJSON.ToObject(str);//(str); 136 | 137 | Console.WriteLine(".net version = " + Environment.Version); 138 | Console.WriteLine(".net os = " + Environment.OSVersion); 139 | //Console.WriteLine("is windows = " + fastBinaryJSON.Reflection.Instance.isWindows); 140 | Console.WriteLine("press key : (E)xotic "); 141 | //if (Console.ReadKey().Key == ConsoleKey.E) 142 | // exotic = true; 143 | 144 | ds = CreateDataset(); 145 | Console.WriteLine("-dataset"); 146 | dsser = false; 147 | //bin_serialize(); 148 | fastjson_serialize(); 149 | //bin_deserialize(); 150 | fastjson_deserialize(); 151 | 152 | //dsser = true; 153 | //Console.WriteLine(); 154 | //Console.WriteLine("+dataset"); 155 | ////bin_serialize(); 156 | //fastjson_serialize(); 157 | ////bin_deserialize(); 158 | //fastjson_deserialize(); 159 | 160 | #region [ other tests] 161 | 162 | // litjson_serialize(); 163 | // jsonnet_serialize(); 164 | // jsonnet4_serialize(); 165 | //stack_serialize(); 166 | 167 | //systemweb_deserialize(); 168 | //bin_deserialize(); 169 | //fastjson_deserialize(); 170 | 171 | // litjson_deserialize(); 172 | // jsonnet_deserialize(); 173 | // jsonnet4_deserialize(); 174 | // stack_deserialize(); 175 | #endregion 176 | Console.ReadKey(); 177 | } 178 | 179 | private static void fastbjson_deserialize(int count) 180 | { 181 | Console.WriteLine(); 182 | Console.WriteLine("fastbjson deserialize"); 183 | List times = new List(); 184 | var data = TestClass.CreateList(20000); 185 | byte[] jsonText = BJSON.ToBJSON(data, new BJSONParameters { UseUnicodeStrings = true }); 186 | //File.WriteAllText("FastJson.json", jsonText); 187 | Stopwatch s = new Stopwatch(); 188 | for (int tests = 0; tests < count; tests++) 189 | { 190 | s.Start(); 191 | var result = BJSON.ToObject>(jsonText); 192 | s.Stop(); 193 | times.Add(s.ElapsedMilliseconds);// DateTime.Now.Subtract(st).TotalMilliseconds); 194 | s.Reset(); 195 | if (tests % 10 == 0) 196 | Console.Write("."); 197 | } 198 | Console.WriteLine(); 199 | 200 | //var min = times.Min(); 201 | //var max = times.Max(); 202 | //var tot = (times.Sum() - max - min) / (count - 2); 203 | //Console.WriteLine($"Min: {times.Min()} Max: {times.Max()} Average: {times.Average()} avg: {tot}"); 204 | Console.WriteLine($"Min: {times.Min()} Max: {times.Max()} Average: {times.Average()}"); 205 | } 206 | 207 | private static string pser(object data) 208 | { 209 | System.Drawing.Point p = (System.Drawing.Point) data; 210 | return p.X.ToString() + "," + p.Y.ToString(); 211 | } 212 | 213 | private static object pdes(string data) 214 | { 215 | string[] ss = data.Split(','); 216 | 217 | return new System.Drawing.Point( 218 | int.Parse(ss[0]), 219 | int.Parse(ss[1]) 220 | ); 221 | } 222 | 223 | private static string tsser(object data) 224 | { 225 | return ((TimeSpan)data).Ticks.ToString(); 226 | } 227 | 228 | private static object tsdes(string data) 229 | { 230 | return new TimeSpan(long.Parse(data)); 231 | } 232 | 233 | public static colclass CreateObject() 234 | { 235 | var c = new colclass(); 236 | 237 | c.booleanValue = true; 238 | c.ordinaryDecimal = 3; 239 | 240 | if (exotic) 241 | { 242 | c.nullableGuid = Guid.NewGuid(); 243 | c.hash = new Hashtable(); 244 | c.bytes = new byte[1024]; 245 | c.stringDictionary = new Dictionary(); 246 | c.objectDictionary = new Dictionary(); 247 | c.intDictionary = new Dictionary(); 248 | c.nullableDouble = 100.003; 249 | 250 | if (dsser) 251 | c.dataset = ds; 252 | c.nullableDecimal = 3.14M; 253 | 254 | c.hash.Add(new class1("0", "hello", Guid.NewGuid()), new class2("1", "code", "desc")); 255 | c.hash.Add(new class2("0", "hello", "pppp"), new class1("1", "code", Guid.NewGuid())); 256 | 257 | c.stringDictionary.Add("name1", new class2("1", "code", "desc")); 258 | c.stringDictionary.Add("name2", new class1("1", "code", Guid.NewGuid())); 259 | 260 | c.intDictionary.Add(1, new class2("1", "code", "desc")); 261 | c.intDictionary.Add(2, new class1("1", "code", Guid.NewGuid())); 262 | 263 | c.objectDictionary.Add(new class1("0", "hello", Guid.NewGuid()), new class2("1", "code", "desc")); 264 | c.objectDictionary.Add(new class2("0", "hello", "pppp"), new class1("1", "code", Guid.NewGuid())); 265 | 266 | c.arrayType = new baseclass[2]; 267 | c.arrayType[0] = new class1(); 268 | c.arrayType[1] = new class2(); 269 | } 270 | 271 | 272 | c.items.Add(new class1("1", "1", Guid.NewGuid())); 273 | c.items.Add(new class2("2", "2", "desc1")); 274 | c.items.Add(new class1("3", "3", Guid.NewGuid())); 275 | c.items.Add(new class2("4", "4", "desc2")); 276 | 277 | c.laststring = "" + DateTime.Now; 278 | 279 | return c; 280 | } 281 | 282 | public static DataSet CreateDataset() 283 | { 284 | DataSet ds = new DataSet(); 285 | for (int j = 1; j < 3; j++) 286 | { 287 | DataTable dt = new DataTable(); 288 | dt.TableName = "Table" + j; 289 | dt.Columns.Add("col1", typeof(int)); 290 | dt.Columns.Add("col2", typeof(string)); 291 | dt.Columns.Add("col3", typeof(Guid)); 292 | dt.Columns.Add("col4", typeof(string)); 293 | dt.Columns.Add("col5", typeof(bool)); 294 | dt.Columns.Add("col6", typeof(string)); 295 | dt.Columns.Add("col7", typeof(string)); 296 | ds.Tables.Add(dt); 297 | Random rrr = new Random(); 298 | for (int i = 0; i < 100; i++) 299 | { 300 | DataRow dr = dt.NewRow(); 301 | dr[0] = rrr.Next(int.MaxValue); 302 | dr[1] = "" + rrr.Next(int.MaxValue); 303 | dr[2] = Guid.NewGuid(); 304 | dr[3] = "" + rrr.Next(int.MaxValue); 305 | dr[4] = true; 306 | dr[5] = "" + rrr.Next(int.MaxValue); 307 | dr[6] = "" + rrr.Next(int.MaxValue); 308 | 309 | dt.Rows.Add(dr); 310 | } 311 | } 312 | return ds; 313 | } 314 | 315 | private static void fastjson_deserialize() 316 | { 317 | Console.WriteLine(); 318 | Console.Write("fastbinaryjson deserialize"); 319 | colclass c = CreateObject(); 320 | for (int pp = 0; pp < tcount; pp++) 321 | { 322 | DateTime st = DateTime.Now; 323 | colclass deserializedStore; 324 | byte[] jsonText = null; 325 | 326 | jsonText = fastBinaryJSON.BJSON.ToBJSON(c); 327 | //Console.WriteLine(" size = " + jsonText.Length); 328 | for (int i = 0; i < count; i++) 329 | { 330 | deserializedStore = (colclass)fastBinaryJSON.BJSON.ToObject(jsonText); 331 | } 332 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds); 333 | } 334 | } 335 | 336 | private static void fastjson_serialize() 337 | { 338 | Console.WriteLine(); 339 | Console.Write("fastbinaryjson serialize"); 340 | colclass c = CreateObject(); 341 | for (int pp = 0; pp < tcount; pp++) 342 | { 343 | DateTime st = DateTime.Now; 344 | byte[] jsonText = null; 345 | for (int i = 0; i < count; i++) 346 | { 347 | jsonText = fastBinaryJSON.BJSON.ToBJSON(c); 348 | } 349 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds); 350 | } 351 | } 352 | 353 | private static void bin_deserialize() 354 | { 355 | Console.WriteLine(); 356 | Console.Write("bin deserialize"); 357 | colclass c = CreateObject(); 358 | for (int pp = 0; pp < tcount; pp++) 359 | { 360 | DateTime st = DateTime.Now; 361 | BinaryFormatter bf = new BinaryFormatter(); 362 | MemoryStream ms = new MemoryStream(); 363 | bf.Serialize(ms, c); 364 | colclass deserializedStore = null; 365 | //Console.WriteLine(" size = " +ms.Length); 366 | for (int i = 0; i < count; i++) 367 | { 368 | ms.Seek(0L, SeekOrigin.Begin); 369 | deserializedStore = (colclass)bf.Deserialize(ms); 370 | } 371 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds); 372 | } 373 | } 374 | 375 | private static void bin_serialize() 376 | { 377 | Console.Write("\r\nbin serialize"); 378 | colclass c = CreateObject(); 379 | for (int pp = 0; pp < tcount; pp++) 380 | { 381 | DateTime st = DateTime.Now; 382 | BinaryFormatter bf = new BinaryFormatter(); 383 | MemoryStream ms = new MemoryStream(); 384 | for (int i = 0; i < count; i++) 385 | { 386 | ms = new MemoryStream(); 387 | bf.Serialize(ms, c); 388 | } 389 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds); 390 | } 391 | } 392 | 393 | 394 | 395 | 396 | #region [ other tests ] 397 | /* 398 | private static void systemweb_serialize() 399 | { 400 | Console.WriteLine(); 401 | Console.Write("msjson serialize"); 402 | colclass c = CreateObject(); 403 | var sws = new System.Web.Script.Serialization.JavaScriptSerializer(); 404 | for (int pp = 0; pp < tcount; pp++) 405 | { 406 | DateTime st = DateTime.Now; 407 | colclass deserializedStore = null; 408 | string jsonText = null; 409 | 410 | //jsonText =sws.Serialize(c); 411 | //Console.WriteLine(" size = " + jsonText.Length); 412 | for (int i = 0; i < count; i++) 413 | { 414 | jsonText =sws.Serialize(c); 415 | //deserializedStore = (colclass)sws.DeserializeObject(jsonText); 416 | } 417 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds ); 418 | } 419 | } 420 | 421 | // private static void stack_serialize() 422 | // { 423 | // Console.WriteLine(); 424 | // Console.Write("stack serialize"); 425 | // colclass c = CreateObject(); 426 | // for (int pp = 0; pp < 5; pp++) 427 | // { 428 | // DateTime st = DateTime.Now; 429 | // string jsonText = null; 430 | // 431 | // for (int i = 0; i < count; i++) 432 | // { 433 | // jsonText = ServiceStack.Text.JsonSerializer.SerializeToString(c); 434 | // } 435 | // Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds ); 436 | // } 437 | // } 438 | 439 | private static void systemweb_deserialize() 440 | // { 441 | // Console.WriteLine(); 442 | // Console.Write("fastjson deserialize"); 443 | // colclass c = CreateObject(); 444 | // var sws = new System.Web.Script.Serialization.JavaScriptSerializer(); 445 | // for (int pp = 0; pp < tcount; pp++) 446 | // { 447 | // DateTime st = DateTime.Now; 448 | // colclass deserializedStore = null; 449 | // string jsonText = null; 450 | // 451 | // jsonText =sws.Serialize(c); 452 | // //Console.WriteLine(" size = " + jsonText.Length); 453 | // for (int i = 0; i < count; i++) 454 | // { 455 | // deserializedStore = (colclass)sws.DeserializeObject(jsonText); 456 | // } 457 | // Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds ); 458 | // } 459 | // } 460 | 461 | private static void jsonnet4_deserialize() 462 | { 463 | Console.WriteLine(); 464 | Console.Write("json.net4 deserialize"); 465 | for (int pp = 0; pp < 5; pp++) 466 | { 467 | DateTime st = DateTime.Now; 468 | colclass c; 469 | colclass deserializedStore = null; 470 | string jsonText = null; 471 | c = Tests.mytests.CreateObject(); 472 | var s = new Newtonsoft.Json.JsonSerializerSettings(); 473 | s.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All; 474 | jsonText = Newtonsoft.Json.JsonConvert.SerializeObject(c, Newtonsoft.Json.Formatting.Indented, s); 475 | for (int i = 0; i < count; i++) 476 | { 477 | deserializedStore = (colclass)Newtonsoft.Json.JsonConvert.DeserializeObject(jsonText, typeof(colclass), s); 478 | } 479 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds ); 480 | } 481 | } 482 | 483 | private static void jsonnet4_serialize() 484 | { 485 | Console.WriteLine(); 486 | Console.Write("json.net4 serialize"); 487 | for (int pp = 0; pp < 5; pp++) 488 | { 489 | DateTime st = DateTime.Now; 490 | colclass c = Tests.mytests.CreateObject(); 491 | Newtonsoft.Json.JsonSerializerSettings s = null; 492 | string jsonText = null; 493 | s = new Newtonsoft.Json.JsonSerializerSettings(); 494 | s.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All; 495 | 496 | for (int i = 0; i < count; i++) 497 | { 498 | jsonText = Newtonsoft.Json.JsonConvert.SerializeObject(c, Newtonsoft.Json.Formatting.Indented, s); 499 | } 500 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds ); 501 | } 502 | } 503 | 504 | private static void stack_deserialize() 505 | { 506 | Console.WriteLine(); 507 | Console.Write("stack deserialize"); 508 | for (int pp = 0; pp < 5; pp++) 509 | { 510 | DateTime st = DateTime.Now; 511 | colclass c; 512 | colclass deserializedStore = null; 513 | string jsonText = null; 514 | c = Tests.mytests.CreateObject(); 515 | jsonText = ServiceStack.Text.JsonSerializer.SerializeToString(c); 516 | for (int i = 0; i < count; i++) 517 | { 518 | deserializedStore = ServiceStack.Text.JsonSerializer.DeserializeFromString(jsonText); 519 | } 520 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds ); 521 | } 522 | } 523 | 524 | private static void jsonnet_deserialize() 525 | { 526 | Console.WriteLine(); 527 | Console.Write("json.net deserialize"); 528 | for (int pp = 0; pp < 5; pp++) 529 | { 530 | DateTime st = DateTime.Now; 531 | colclass c; 532 | colclass deserializedStore = null; 533 | string jsonText = null; 534 | c = Tests.mytests.CreateObject(); 535 | var s = new json.net.JsonSerializerSettings(); 536 | s.TypeNameHandling = json.net.TypeNameHandling.All; 537 | jsonText = json.net.JsonConvert.SerializeObject(c, json.net.Formatting.Indented, s); 538 | for (int i = 0; i < count; i++) 539 | { 540 | deserializedStore = (colclass)json.net.JsonConvert.DeserializeObject(jsonText, typeof(colclass), s); 541 | } 542 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds ); 543 | } 544 | } 545 | 546 | private static void jsonnet_serialize() 547 | { 548 | Console.WriteLine(); 549 | Console.Write("json.net serialize"); 550 | for (int pp = 0; pp < 5; pp++) 551 | { 552 | DateTime st = DateTime.Now; 553 | colclass c = Tests.mytests.CreateObject(); 554 | json.net.JsonSerializerSettings s = null; 555 | string jsonText = null; 556 | s = new json.net.JsonSerializerSettings(); 557 | s.TypeNameHandling = json.net.TypeNameHandling.All; 558 | 559 | for (int i = 0; i < count; i++) 560 | { 561 | jsonText = json.net.JsonConvert.SerializeObject(c, json.net.Formatting.Indented, s); 562 | } 563 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds ); 564 | } 565 | } 566 | 567 | private static void litjson_deserialize() 568 | { 569 | Console.WriteLine(); 570 | Console.Write("litjson deserialize"); 571 | for (int pp = 0; pp < 5; pp++) 572 | { 573 | DateTime st = DateTime.Now; 574 | colclass c; 575 | colclass deserializedStore = null; 576 | string jsonText = null; 577 | c = Tests.mytests.CreateObject(); 578 | jsonText = BizFX.Common.JSON.JsonMapper.ToJson(c); 579 | for (int i = 0; i < count; i++) 580 | { 581 | deserializedStore = (colclass)BizFX.Common.JSON.JsonMapper.ToObject(jsonText); 582 | } 583 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds ); 584 | } 585 | } 586 | 587 | private static void litjson_serialize() 588 | { 589 | Console.WriteLine(); 590 | Console.Write("litjson serialize"); 591 | for (int pp = 0; pp < 5; pp++) 592 | { 593 | DateTime st = DateTime.Now; 594 | colclass c; 595 | string jsonText = null; 596 | c = Tests.mytests.CreateObject(); 597 | for (int i = 0; i < count; i++) 598 | { 599 | jsonText = BizFX.Common.JSON.JsonMapper.ToJson(c); 600 | } 601 | Console.Write("\t" + DateTime.Now.Subtract(st).TotalMilliseconds ); 602 | } 603 | } 604 | 605 | 606 | */ 607 | #endregion 608 | } 609 | } -------------------------------------------------------------------------------- /Consoletest/consoletest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | {6BADD8B3-618E-412A-BBCA-8420EFD5B62E} 5 | Debug 6 | x86 7 | Exe 8 | consoletest 9 | consoletest 10 | v4.0 11 | Properties 12 | True 13 | False 14 | 4 15 | false 16 | 17 | 18 | 19 | 20 | False 21 | Auto 22 | 4194304 23 | AnyCPU 24 | 4096 25 | 26 | 27 | bin\Debug\ 28 | true 29 | Full 30 | True 31 | False 32 | DEBUG;TRACE 33 | 34 | 35 | bin\Release\ 36 | False 37 | None 38 | True 39 | False 40 | TRACE 41 | 42 | 43 | False 44 | Auto 45 | 4194304 46 | x86 47 | 4096 48 | 49 | 50 | false 51 | AnyCPU 52 | false 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | {207e91b1-c9f8-4913-88e1-3549ef5f3273} 69 | fastBinaryJSON 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /Consoletest/dataobjects.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | 6 | namespace consoletest 7 | { 8 | 9 | #region [ data objects ] 10 | 11 | [Serializable()] 12 | public class baseclass 13 | { 14 | public string Name { get; set; } 15 | public string Code { get; set; } 16 | } 17 | 18 | [Serializable()] 19 | public class class1 : baseclass 20 | { 21 | public class1() { } 22 | public class1(string name, string code, Guid g) 23 | { 24 | Name = name; 25 | Code = code; 26 | guid = g; 27 | } 28 | public Guid guid { get; set; } 29 | } 30 | 31 | [Serializable()] 32 | public class class2 : baseclass 33 | { 34 | public class2() { } 35 | public class2(string name, string code, string desc) 36 | { 37 | Name = name; 38 | Code = code; 39 | description = desc; 40 | } 41 | public string description { get; set; } 42 | } 43 | 44 | public enum Gender 45 | { 46 | Male, 47 | Female 48 | } 49 | 50 | [Serializable()] 51 | public class colclass 52 | { 53 | public colclass() 54 | { 55 | items = new List(); 56 | //date = DateTime.Now; 57 | multilineString = @" 58 | AJKLjaskljLA 59 | ahjksjkAHJKS سلام فارسی 60 | AJKHSKJhaksjhAHSJKa 61 | AJKSHajkhsjkHKSJKash 62 | ASJKhasjkKASJKahsjk 63 | "; 64 | isNew = true; 65 | booleanValue = true; 66 | ordinaryDouble = 0.001; 67 | gender = Gender.Female; 68 | intarray = new int[5] {1,2,3,4,5}; 69 | } 70 | public bool booleanValue { get; set; } 71 | public DateTime date {get; set;} 72 | public string multilineString { get; set; } 73 | public List items { get; set; } 74 | public decimal ordinaryDecimal {get; set;} 75 | public double ordinaryDouble { get; set ;} 76 | public bool isNew { get; set; } 77 | public string laststring { get; set; } 78 | public Gender gender { get; set; } 79 | 80 | public DataSet dataset { get; set; } 81 | public Dictionary stringDictionary { get; set; } 82 | public Dictionary objectDictionary { get; set; } 83 | public Dictionary intDictionary { get; set; } 84 | public Guid? nullableGuid {get; set;} 85 | public decimal? nullableDecimal { get; set; } 86 | public double? nullableDouble { get; set; } 87 | public Hashtable hash { get; set; } 88 | public baseclass[] arrayType { get; set; } 89 | public byte[] bytes { get; set; } 90 | public int[] intarray { get; set; } 91 | 92 | } 93 | #endregion 94 | 95 | } 96 | -------------------------------------------------------------------------------- /Consoletest/mytests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.IO; 6 | using System.Reflection; 7 | using System.Runtime.Serialization.Formatters.Binary; 8 | using System.Text; 9 | using fastJSON; 10 | 11 | 12 | namespace Tests 13 | { 14 | #region 15 | 16 | [Serializable()] 17 | public class baseclass 18 | { 19 | public string Name { get; set; } 20 | public string Code { get; set; } 21 | } 22 | 23 | [Serializable()] 24 | public class class1 : baseclass 25 | { 26 | public class1() { } 27 | public class1(string name, string code, Guid g) 28 | { 29 | Name = name; 30 | Code = code; 31 | guid = g; 32 | } 33 | public Guid guid { get; set; } 34 | } 35 | 36 | [Serializable()] 37 | public class class2 : baseclass 38 | { 39 | public class2() { } 40 | public class2(string name, string code, string desc) 41 | { 42 | Name = name; 43 | Code = code; 44 | description = desc; 45 | } 46 | public string description { get; set; } 47 | } 48 | 49 | [Serializable()] 50 | public class colclass 51 | { 52 | public colclass() 53 | { 54 | items = new List(); 55 | date = DateTime.Now; 56 | Ppp = @" 57 | AJKLjaskljLA 58 | ahjksjkAHJKS 59 | AJKHSKJhaksjhAHSJKa 60 | AJKSHajkhsjkHKSJKash 61 | ASJKhasjkKASJKahsjk 62 | "; 63 | gggg = Guid.NewGuid(); 64 | //hash = new Hashtable(); 65 | isNew = true; 66 | done= true; 67 | } 68 | public bool done { get; set; } 69 | public DateTime date {get; set;} 70 | //public DataSet ds { get; set; } 71 | public string Ppp { get; set; } 72 | public List items { get; set; } 73 | public Guid gggg {get; set;} 74 | public decimal? dec {get; set;} 75 | public bool isNew { get; set; } 76 | //public Hashtable hash { get; set; } 77 | 78 | } 79 | #endregion 80 | 81 | [TestFixture] 82 | public class mytests : TestFixtureBase 83 | { 84 | public mytests() 85 | { 86 | ds = CreateDataset(); 87 | Console.WriteLine("count = " + count); 88 | } 89 | static DataSet ds; 90 | int count = 1000; 91 | 92 | [Test] 93 | public void a_new_serializer() 94 | { 95 | DateTime st = DateTime.Now; 96 | colclass c; 97 | string jsonText = null; 98 | c= CreateObject(); 99 | for (int i = 0; i < count; i++) 100 | { 101 | jsonText = JSON.Instance.ToJSON(c); 102 | } 103 | //colclass deserializedStore = ServiceStack.Text.JsonSerializer.DeserializeFromString(jsonText); 104 | //Console.WriteLine("Size = " + jsonText.Length); 105 | Console.WriteLine("time ms = " + DateTime.Now.Subtract(st).TotalMilliseconds); 106 | } 107 | 108 | [Test] 109 | public void b_new_deserializer() 110 | { 111 | DateTime st = DateTime.Now; 112 | colclass c; 113 | string jsonText = null; 114 | c= CreateObject(); 115 | object o ; 116 | jsonText = JSON.Instance.ToJSON(c); 117 | for (int i = 0; i < count; i++) 118 | { 119 | o=JSON.Instance.ToObject(jsonText); 120 | } 121 | //colclass deserializedStore = ServiceStack.Text.JsonSerializer.DeserializeFromString(jsonText); 122 | //Console.WriteLine("Size = " + jsonText.Length); 123 | Console.WriteLine("time ms = " + DateTime.Now.Subtract(st).TotalMilliseconds); 124 | } 125 | 126 | [Test] 127 | public void a_Stack_Serializer() 128 | { 129 | DateTime st = DateTime.Now; 130 | colclass c; 131 | string jsonText = null; 132 | c= CreateObject(); 133 | for (int i = 0; i < count; i++) 134 | { 135 | jsonText = ServiceStack.Text.JsonSerializer.SerializeToString(c); 136 | } 137 | //colclass deserializedStore = ServiceStack.Text.JsonSerializer.DeserializeFromString(jsonText); 138 | //Console.WriteLine("Size = " + jsonText.Length); 139 | Console.WriteLine("time ms = " + DateTime.Now.Subtract(st).TotalMilliseconds); 140 | } 141 | 142 | 143 | [Test] 144 | public void a_Lit_Serializer() 145 | { 146 | DateTime st = DateTime.Now; 147 | colclass c; 148 | string jsonText = null; 149 | c= CreateObject(); 150 | for (int i = 0; i < count; i++) 151 | { 152 | jsonText = JSON.Instance.ToJSON(c); 153 | } 154 | //object deserializedStore = JsonMapper.ToObject(jsonText); 155 | //Console.WriteLine("Size = " + jsonText.Length); 156 | Console.WriteLine("time ms = " + DateTime.Now.Subtract(st).TotalMilliseconds); 157 | } 158 | 159 | [Test] 160 | public void a_nJson_Serializer() 161 | { 162 | DateTime st = DateTime.Now; 163 | colclass c; 164 | JsonSerializerSettings s = null; 165 | string jsonText = null; 166 | s = new JsonSerializerSettings(); 167 | s.TypeNameHandling = TypeNameHandling.All; 168 | c= CreateObject(); 169 | 170 | for (int i = 0; i < count; i++) 171 | { 172 | jsonText = JsonConvert.SerializeObject(c, Formatting.Indented, s); 173 | } 174 | //Console.WriteLine("Size = " + jsonText.Length); 175 | //colclass deserializedStore = (colclass)JsonConvert.DeserializeObject(jsonText, typeof(colclass), s); 176 | Console.WriteLine("time ms = " + DateTime.Now.Subtract(st).TotalMilliseconds); 177 | } 178 | 179 | 180 | [Test] 181 | public void b_nJson_DeSerializer() 182 | { 183 | DateTime st = DateTime.Now; 184 | colclass c; 185 | colclass deserializedStore = null; 186 | JsonSerializerSettings s = null; 187 | string jsonText = null; 188 | c= CreateObject(); 189 | s = new JsonSerializerSettings(); 190 | s.TypeNameHandling = TypeNameHandling.All; 191 | jsonText = JsonConvert.SerializeObject(c, Formatting.Indented, s); 192 | for (int i = 0; i < count; i++) 193 | { 194 | deserializedStore = (colclass)JsonConvert.DeserializeObject(jsonText, typeof(colclass), s); 195 | } 196 | //WriteObject(deserializedStore); 197 | Console.WriteLine("time ms = " + DateTime.Now.Subtract(st).TotalMilliseconds); 198 | } 199 | 200 | [Test] 201 | public void b_bin_DeSerializer() 202 | { 203 | DateTime st = DateTime.Now; 204 | colclass c; 205 | colclass deserializedStore= null; 206 | c= CreateObject(); 207 | BinaryFormatter bf = new BinaryFormatter(); 208 | MemoryStream ms = new MemoryStream(); 209 | bf.Serialize(ms,c); 210 | 211 | for (int i = 0; i < count; i++) 212 | { 213 | ms.Seek(0L,SeekOrigin.Begin); 214 | deserializedStore = (colclass)bf.Deserialize(ms); 215 | } 216 | //WriteObject(deserializedStore); 217 | Console.WriteLine("time ms = " + DateTime.Now.Subtract(st).TotalMilliseconds); 218 | } 219 | 220 | [Test] 221 | public void a_bin_Serializer() 222 | { 223 | DateTime st = DateTime.Now; 224 | colclass c; 225 | c= CreateObject(); 226 | BinaryFormatter bf = new BinaryFormatter(); 227 | MemoryStream ms = new MemoryStream(); 228 | for (int i = 0; i < count; i++) 229 | { 230 | ms=new MemoryStream(); 231 | bf.Serialize(ms,c); 232 | } 233 | //WriteObject(deserializedStore); 234 | //Console.WriteLine("Size = " + ms.Length); 235 | Console.WriteLine("time ms = " + DateTime.Now.Subtract(st).TotalMilliseconds); 236 | } 237 | 238 | [Test] 239 | public void b_Stack_DeSerializer() 240 | { 241 | DateTime st = DateTime.Now; 242 | colclass c; 243 | colclass deserializedStore= null; 244 | string jsonText = null; 245 | c= CreateObject(); 246 | jsonText = ServiceStack.Text.JsonSerializer.SerializeToString(c); 247 | for (int i = 0; i < count; i++) 248 | { 249 | deserializedStore = ServiceStack.Text.JsonSerializer.DeserializeFromString(jsonText); 250 | } 251 | //WriteObject(deserializedStore); 252 | Console.WriteLine("time ms = " + DateTime.Now.Subtract(st).TotalMilliseconds); 253 | } 254 | 255 | public static colclass CreateObject() 256 | { 257 | var c = new colclass(); 258 | //c.ppp = "hello"; 259 | //c.ds = ds; 260 | //c.hash.Add("pppp",new class1("1", "1", Guid.NewGuid())); 261 | //c.hash.Add(22,new class2("2", "2", "desc1")); 262 | c.done=true; 263 | c.items.Add(new class1("1", "1", Guid.NewGuid())); 264 | c.items.Add(new class2("2", "2", "desc1")); 265 | c.items.Add(new class1("3", "3", Guid.NewGuid())); 266 | c.items.Add(new class2("4", "4", "desc2")); 267 | return c; 268 | } 269 | 270 | [Test] 271 | public void b_Lit_DeSerializer() 272 | { 273 | DateTime st = DateTime.Now; 274 | colclass c; 275 | colclass deserializedStore=null; 276 | string jsonText = null; 277 | c= CreateObject(); 278 | jsonText = JSON.Instance.ToJSON(c); 279 | for (int i = 0; i < count; i++) 280 | { 281 | deserializedStore = (colclass)JSON.Instance.ToObject(jsonText); 282 | } 283 | //WriteObject(deserializedStore); 284 | Console.WriteLine("time ms = " + DateTime.Now.Subtract(st).TotalMilliseconds); 285 | } 286 | 287 | private void WriteObject(colclass obj) 288 | { 289 | foreach(object c in obj.items) 290 | ;//Console.WriteLine(""+c.GetType()); 291 | } 292 | 293 | public static DataSet CreateDataset() 294 | { 295 | DataSet ds = new DataSet(); 296 | for (int j = 1; j < 3; j++) 297 | { 298 | DataTable dt = new DataTable(); 299 | dt.TableName = "Table" + j; 300 | dt.Columns.Add("col1", typeof(int)); 301 | dt.Columns.Add("col2", typeof(string)); 302 | dt.Columns.Add("col3", typeof(Guid)); 303 | dt.Columns.Add("col4", typeof(string)); 304 | dt.Columns.Add("col5", typeof(bool)); 305 | dt.Columns.Add("col6", typeof(string)); 306 | dt.Columns.Add("col7", typeof(string)); 307 | ds.Tables.Add(dt); 308 | Random rrr = new Random(); 309 | for (int i = 0; i < 100; i++) 310 | { 311 | DataRow dr = dt.NewRow(); 312 | dr[0] = rrr.Next(int.MaxValue); 313 | dr[1] = "" + rrr.Next(int.MaxValue); 314 | dr[2] = Guid.NewGuid(); 315 | dr[3] = "" + rrr.Next(int.MaxValue); 316 | dr[4] = true; 317 | dr[5] = "" + rrr.Next(int.MaxValue); 318 | dr[6] = "" + rrr.Next(int.MaxValue); 319 | 320 | dt.Rows.Add(dr); 321 | } 322 | } 323 | return ds; 324 | } 325 | } 326 | } 327 | -------------------------------------------------------------------------------- /UnitTests.nunit: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /UnitTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("UnitTests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Microsoft")] 11 | [assembly: AssemblyProduct("UnitTests")] 12 | [assembly: AssemblyCopyright("Copyright © Microsoft 2011")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("d9760175-5f53-4859-9e05-4f48d62d4219")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /UnitTests/UnitTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {F4BFF0D2-45F6-413B-B1E7-BC4A0D6596FC} 9 | Library 10 | Properties 11 | UnitTests 12 | UnitTests 13 | v4.0 14 | 512 15 | 16 | 17 | 18 | 19 | 20 | 21 | 3.5 22 | 23 | 24 | true 25 | full 26 | false 27 | bin\Debug\ 28 | TRACE;DEBUG;NET4 29 | prompt 30 | 4 31 | 32 | 33 | pdbonly 34 | true 35 | bin\Release\ 36 | TRACE 37 | prompt 38 | 4 39 | 40 | 41 | false 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | False 51 | C:\Program Files (x86)\NUnit 2.5.10\bin\net-2.0\framework\nunit.framework.dll 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | {207e91b1-c9f8-4913-88e1-3549ef5f3273} 64 | fastBinaryJSON 65 | 66 | 67 | 68 | 75 | -------------------------------------------------------------------------------- /fastBinaryJSON 3.5/fastBinaryJSON net35.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {A87C4070-065B-4012-9EF0-184AA60B5CC9} 9 | Library 10 | Properties 11 | fastBinaryJSON 12 | fastBinaryJSON 13 | v2.0 14 | 512 15 | True 16 | False 17 | false 18 | true 19 | False 20 | OnBuildSuccess 21 | 22 | 23 | 24 | 25 | 3.5 26 | 27 | 28 | publish\ 29 | true 30 | Disk 31 | false 32 | Foreground 33 | 7 34 | Days 35 | false 36 | false 37 | true 38 | 0 39 | 1.0.0.%2a 40 | false 41 | false 42 | true 43 | 44 | 45 | true 46 | Full 47 | false 48 | ..\output\net20\ 49 | prompt 50 | 4 51 | 52 | 53 | false 54 | 55 | 56 | full 57 | true 58 | bin\Release\ 59 | prompt 60 | 4 61 | true 62 | false 63 | 64 | 65 | False 66 | Project 67 | 68 | 69 | False 70 | Off 71 | 4194304 72 | AnyCPU 73 | 74 | 75 | TRACE 76 | 77 | 78 | ..\fastbinaryjson\fastJSON.snk 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | False 88 | Microsoft .NET Framework 4 %28x86 and x64%29 89 | true 90 | 91 | 92 | False 93 | .NET Framework 3.5 SP1 Client Profile 94 | false 95 | 96 | 97 | False 98 | .NET Framework 3.5 SP1 99 | false 100 | 101 | 102 | False 103 | Windows Installer 3.1 104 | true 105 | 106 | 107 | 108 | 109 | AssemblyInfo.cs 110 | 111 | 112 | BJSON.cs 113 | 114 | 115 | BJsonParser.cs 116 | 117 | 118 | BJsonSerializer.cs 119 | 120 | 121 | dynamic.cs 122 | 123 | 124 | Getters.cs 125 | 126 | 127 | Reflection.cs 128 | 129 | 130 | SafeDictionary.cs 131 | 132 | 133 | 134 | 141 | -------------------------------------------------------------------------------- /fastBinaryJSON.nuspec: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | fastBinaryJSON 5 | 1.6.1.0 6 | fastBinaryJSON 7 | mgholam 8 | 9 | https://www.codeproject.com/Articles/345070/fastBinaryJSON 10 | false 11 | smallest, fastest polymorphic binary JSON serializer 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /fastBinaryJSON.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2026 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "consoletest", "consoletest\consoletest.csproj", "{6BADD8B3-618E-412A-BBCA-8420EFD5B62E}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "fastBinaryJSON", "fastBinaryJSON\fastBinaryJSON.csproj", "{207E91B1-C9F8-4913-88E1-3549EF5F3273}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{F4BFF0D2-45F6-413B-B1E7-BC4A0D6596FC}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "fastBinaryJSON net35", "fastBinaryJSON 3.5\fastBinaryJSON net35.csproj", "{A87C4070-065B-4012-9EF0-184AA60B5CC9}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Debug|x86 = Debug|x86 18 | Release|Any CPU = Release|Any CPU 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {6BADD8B3-618E-412A-BBCA-8420EFD5B62E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {6BADD8B3-618E-412A-BBCA-8420EFD5B62E}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {6BADD8B3-618E-412A-BBCA-8420EFD5B62E}.Debug|x86.ActiveCfg = Debug|x86 25 | {6BADD8B3-618E-412A-BBCA-8420EFD5B62E}.Debug|x86.Build.0 = Debug|x86 26 | {6BADD8B3-618E-412A-BBCA-8420EFD5B62E}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {6BADD8B3-618E-412A-BBCA-8420EFD5B62E}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {6BADD8B3-618E-412A-BBCA-8420EFD5B62E}.Release|x86.ActiveCfg = Release|x86 29 | {6BADD8B3-618E-412A-BBCA-8420EFD5B62E}.Release|x86.Build.0 = Release|x86 30 | {207E91B1-C9F8-4913-88E1-3549EF5F3273}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {207E91B1-C9F8-4913-88E1-3549EF5F3273}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {207E91B1-C9F8-4913-88E1-3549EF5F3273}.Debug|x86.ActiveCfg = Debug|Any CPU 33 | {207E91B1-C9F8-4913-88E1-3549EF5F3273}.Debug|x86.Build.0 = Debug|Any CPU 34 | {207E91B1-C9F8-4913-88E1-3549EF5F3273}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {207E91B1-C9F8-4913-88E1-3549EF5F3273}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {207E91B1-C9F8-4913-88E1-3549EF5F3273}.Release|x86.ActiveCfg = Release|Any CPU 37 | {207E91B1-C9F8-4913-88E1-3549EF5F3273}.Release|x86.Build.0 = Release|Any CPU 38 | {F4BFF0D2-45F6-413B-B1E7-BC4A0D6596FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {F4BFF0D2-45F6-413B-B1E7-BC4A0D6596FC}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {F4BFF0D2-45F6-413B-B1E7-BC4A0D6596FC}.Debug|x86.ActiveCfg = Debug|Any CPU 41 | {F4BFF0D2-45F6-413B-B1E7-BC4A0D6596FC}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {F4BFF0D2-45F6-413B-B1E7-BC4A0D6596FC}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {F4BFF0D2-45F6-413B-B1E7-BC4A0D6596FC}.Release|x86.ActiveCfg = Release|Any CPU 44 | {A87C4070-065B-4012-9EF0-184AA60B5CC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {A87C4070-065B-4012-9EF0-184AA60B5CC9}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | {A87C4070-065B-4012-9EF0-184AA60B5CC9}.Debug|x86.ActiveCfg = Debug|Any CPU 47 | {A87C4070-065B-4012-9EF0-184AA60B5CC9}.Debug|x86.Build.0 = Debug|Any CPU 48 | {A87C4070-065B-4012-9EF0-184AA60B5CC9}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {A87C4070-065B-4012-9EF0-184AA60B5CC9}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {A87C4070-065B-4012-9EF0-184AA60B5CC9}.Release|x86.ActiveCfg = Release|Any CPU 51 | {A87C4070-065B-4012-9EF0-184AA60B5CC9}.Release|x86.Build.0 = Release|Any CPU 52 | EndGlobalSection 53 | GlobalSection(SolutionProperties) = preSolution 54 | HideSolutionNode = FALSE 55 | EndGlobalSection 56 | GlobalSection(ExtensibilityGlobals) = postSolution 57 | SolutionGuid = {96DAED93-DC72-437E-8DA8-D0748BA54E17} 58 | EndGlobalSection 59 | EndGlobal 60 | -------------------------------------------------------------------------------- /fastBinaryJSON/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("fastBinaryJSON")] 5 | [assembly: AssemblyDescription("smallest fastest polymorphic binary json serializer")] 6 | [assembly: AssemblyProduct("fastBinaryJSON")] 7 | [assembly: AssemblyCopyright("2010-2018")] 8 | 9 | [assembly: ComVisible(false)] 10 | 11 | [assembly: AssemblyVersion("1.6.0.0")] 12 | [assembly: AssemblyFileVersion("1.6.1.0")] 13 | -------------------------------------------------------------------------------- /fastBinaryJSON/BJSON.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | #if !SILVERLIGHT 5 | using System.Data; 6 | #endif 7 | using System.IO; 8 | using System.Collections.Specialized; 9 | using fastJSON; 10 | 11 | namespace fastBinaryJSON 12 | { 13 | public sealed class TOKENS 14 | { 15 | public const byte DOC_START = 1; 16 | public const byte DOC_END = 2; 17 | public const byte ARRAY_START = 3; 18 | public const byte ARRAY_END = 4; 19 | public const byte COLON = 5; 20 | public const byte COMMA = 6; 21 | public const byte NAME = 7; 22 | public const byte STRING = 8; 23 | public const byte BYTE = 9; 24 | public const byte INT = 10; 25 | public const byte UINT = 11; 26 | public const byte LONG = 12; 27 | public const byte ULONG = 13; 28 | public const byte SHORT = 14; 29 | public const byte USHORT = 15; 30 | public const byte DATETIME = 16; 31 | public const byte GUID = 17; 32 | public const byte DOUBLE = 18; 33 | public const byte FLOAT = 19; 34 | public const byte DECIMAL = 20; 35 | public const byte CHAR = 21; 36 | public const byte BYTEARRAY = 22; 37 | public const byte NULL = 23; 38 | public const byte TRUE = 24; 39 | public const byte FALSE = 25; 40 | public const byte UNICODE_STRING = 26; 41 | public const byte DATETIMEOFFSET = 27; 42 | public const byte ARRAY_TYPED = 28; 43 | public const byte TYPES_POINTER = 29; 44 | public const byte TIMESPAN = 30; 45 | public const byte ARRAY_TYPED_LONG = 31; 46 | public const byte NAME_UNI = 32; 47 | } 48 | 49 | public class typedarray 50 | { 51 | public string typename; 52 | public int count; 53 | public List data = new List(); 54 | } 55 | 56 | 57 | 58 | public sealed class BJSONParameters 59 | { 60 | /// 61 | /// Optimize the schema for Datasets (default = True) 62 | /// 63 | public bool UseOptimizedDatasetSchema = true; 64 | /// 65 | /// Serialize readonly properties (default = False) 66 | /// 67 | public bool ShowReadOnlyProperties = false; 68 | /// 69 | /// Use global types $types for more compact size when using a lot of classes (default = True) 70 | /// 71 | public bool UsingGlobalTypes = true; 72 | /// 73 | /// Use Unicode strings = T (faster), Use UTF8 strings = F (smaller) (default = True) 74 | /// 75 | public bool UseUnicodeStrings = true; 76 | /// 77 | /// Serialize Null values to the output (default = False) 78 | /// 79 | public bool SerializeNulls = false; 80 | /// 81 | /// Enable fastBinaryJSON extensions $types, $type, $map (default = True) 82 | /// 83 | public bool UseExtensions = true; 84 | /// 85 | /// Anonymous types have read only properties 86 | /// 87 | public bool EnableAnonymousTypes = false; 88 | /// 89 | /// Use the UTC date format (default = False) 90 | /// 91 | public bool UseUTCDateTime = false; 92 | /// 93 | /// Ignore attributes to check for (default : XmlIgnoreAttribute, NonSerialized) 94 | /// 95 | public List IgnoreAttributes = new List { typeof(System.Xml.Serialization.XmlIgnoreAttribute), typeof(NonSerializedAttribute) }; 96 | /// 97 | /// If you have parametric and no default constructor for you classes (default = False) 98 | /// 99 | /// IMPORTANT NOTE : If True then all initial values within the class will be ignored and will be not set 100 | /// 101 | public bool ParametricConstructorOverride = false; 102 | /// 103 | /// Maximum depth the serializer will go to to avoid loops (default = 20 levels) 104 | /// 105 | public short SerializerMaxDepth = 20; 106 | /// 107 | /// Use typed arrays t[] into object = t[] not object[] (default = true) 108 | /// 109 | public bool UseTypedArrays = true; 110 | /// 111 | /// Backward compatible Typed array type name as UTF8 (default = false -> fast v1.5 unicode) 112 | /// 113 | public bool v1_4TypedArray = false; 114 | 115 | //public bool OptimizeSize = false; 116 | 117 | 118 | public void FixValues() 119 | { 120 | if (UseExtensions == false) // disable conflicting params 121 | UsingGlobalTypes = false; 122 | 123 | if (EnableAnonymousTypes) 124 | ShowReadOnlyProperties = true; 125 | } 126 | 127 | internal BJSONParameters MakeCopy() 128 | { 129 | return new BJSONParameters 130 | { 131 | UseOptimizedDatasetSchema = UseOptimizedDatasetSchema, 132 | ShowReadOnlyProperties = ShowReadOnlyProperties, 133 | EnableAnonymousTypes = EnableAnonymousTypes, 134 | UsingGlobalTypes = UsingGlobalTypes, 135 | IgnoreAttributes = new List(IgnoreAttributes), 136 | UseUnicodeStrings = UseUnicodeStrings, 137 | SerializeNulls = SerializeNulls, 138 | ParametricConstructorOverride = ParametricConstructorOverride, 139 | SerializerMaxDepth = SerializerMaxDepth, 140 | UseTypedArrays = UseTypedArrays, 141 | UseExtensions = UseExtensions, 142 | UseUTCDateTime = UseUTCDateTime, 143 | v1_4TypedArray = v1_4TypedArray//, 144 | //OptimizeSize = OptimizeSize 145 | 146 | }; 147 | } 148 | } 149 | 150 | public static class BJSON 151 | { 152 | /// 153 | /// Globally set-able parameters for controlling the serializer 154 | /// 155 | public static BJSONParameters Parameters = new BJSONParameters(); 156 | /// 157 | /// Parse a json and generate a Dictionary<string,object> or List<object> structure 158 | /// 159 | /// 160 | /// 161 | public static object Parse(byte[] json) 162 | { 163 | return new BJsonParser(json, Parameters.UseUTCDateTime, Parameters.v1_4TypedArray).Decode(); 164 | } 165 | #if NET4 166 | /// 167 | /// Create a .net4 dynamic object from the binary json byte array 168 | /// 169 | /// 170 | /// 171 | public static dynamic ToDynamic(byte[] json) 172 | { 173 | return new DynamicJson(json); 174 | } 175 | #endif 176 | /// 177 | /// Register custom type handlers for your own types not natively handled by fastBinaryJSON 178 | /// 179 | /// 180 | /// 181 | /// 182 | public static void RegisterCustomType(Type type, Reflection.Serialize serializer, Reflection.Deserialize deserializer) 183 | { 184 | Reflection.Instance.RegisterCustomType(type, serializer, deserializer); 185 | } 186 | /// 187 | /// Create a binary json representation for an object 188 | /// 189 | /// 190 | /// 191 | public static byte[] ToBJSON(object obj) 192 | { 193 | return ToBJSON(obj, Parameters); 194 | } 195 | /// 196 | /// Create a binary json representation for an object with parameter override on this call 197 | /// 198 | /// 199 | /// 200 | /// 201 | public static byte[] ToBJSON(object obj, BJSONParameters param) 202 | { 203 | param.FixValues(); 204 | param = param.MakeCopy(); 205 | Type t = null; 206 | if (obj == null) 207 | return new byte[] { TOKENS.NULL }; 208 | if (obj.GetType().IsGenericType) 209 | t = Reflection.Instance.GetGenericTypeDefinition(obj.GetType());// obj.GetType().GetGenericTypeDefinition(); 210 | if (t == typeof(Dictionary<,>) || t == typeof(List<>)) 211 | param.UsingGlobalTypes = false; 212 | // FEATURE : enable extensions when you can deserialize anon types 213 | if (param.EnableAnonymousTypes) { param.UseExtensions = false; param.UsingGlobalTypes = false; } 214 | 215 | return new BJSONSerializer(param).ConvertToBJSON(obj); 216 | } 217 | /// 218 | /// Fill a given object with the binary json represenation 219 | /// 220 | /// 221 | /// 222 | /// 223 | public static object FillObject(object input, byte[] json) 224 | { 225 | return new deserializer(Parameters).FillObject(input, json); 226 | } 227 | /// 228 | /// Create a generic object from the json 229 | /// 230 | /// 231 | /// 232 | /// 233 | public static T ToObject(byte[] json) 234 | { 235 | return new deserializer(Parameters).ToObject(json); 236 | } 237 | /// 238 | /// Create a generic object from the json with parameter override on this call 239 | /// 240 | /// 241 | /// 242 | /// 243 | /// 244 | public static T ToObject(byte[] json, BJSONParameters param) 245 | { 246 | return new deserializer(param).ToObject(json); 247 | } 248 | /// 249 | /// Create an object from the json 250 | /// 251 | /// 252 | /// 253 | public static object ToObject(byte[] json) 254 | { 255 | return new deserializer(Parameters).ToObject(json, null); 256 | } 257 | /// 258 | /// Create an object from the json with parameter override on this call 259 | /// 260 | /// 261 | /// 262 | /// 263 | public static object ToObject(byte[] json, BJSONParameters param) 264 | { 265 | param.FixValues(); 266 | param = param.MakeCopy(); 267 | return new deserializer(param).ToObject(json, null); 268 | } 269 | /// 270 | /// Create a typed object from the json 271 | /// 272 | /// 273 | /// 274 | /// 275 | public static object ToObject(byte[] json, Type type) 276 | { 277 | return new deserializer(Parameters).ToObject(json, type); 278 | } 279 | /// 280 | /// Clear the internal reflection cache so you can start from new (you will loose performance) 281 | /// 282 | public static void ClearReflectionCache() 283 | { 284 | Reflection.Instance.ClearReflectionCache(); 285 | } 286 | /// 287 | /// Deep copy an object i.e. clone to a new object 288 | /// 289 | /// 290 | /// 291 | public static object DeepCopy(object obj) 292 | { 293 | return new deserializer(Parameters).ToObject(ToBJSON(obj)); 294 | } 295 | } 296 | 297 | internal class deserializer 298 | { 299 | public deserializer(BJSONParameters param) 300 | { 301 | _params = param; 302 | _params = param.MakeCopy(); 303 | } 304 | 305 | private BJSONParameters _params; 306 | private Dictionary _circobj = new Dictionary(); 307 | private Dictionary _cirrev = new Dictionary(); 308 | 309 | public T ToObject(byte[] json) 310 | { 311 | return (T)ToObject(json, typeof(T)); 312 | } 313 | 314 | public object ToObject(byte[] json) 315 | { 316 | return ToObject(json, null); 317 | } 318 | 319 | public object ToObject(byte[] json, Type type) 320 | { 321 | //_params.FixValues(); 322 | Type t = null; 323 | if (type != null && type.IsGenericType) 324 | t = Reflection.Instance.GetGenericTypeDefinition(type);// type.GetGenericTypeDefinition(); 325 | _globalTypes = _params.UsingGlobalTypes; 326 | if (t == typeof(Dictionary<,>) || t == typeof(List<>)) 327 | _globalTypes = false; 328 | 329 | var o = new BJsonParser(json, _params.UseUTCDateTime, _params.v1_4TypedArray).Decode(); 330 | if (type?.IsEnum == true) return CreateEnum(type, o); 331 | #if !SILVERLIGHT 332 | if (type != null && type == typeof(DataSet)) 333 | return CreateDataset(o as Dictionary, null); 334 | 335 | if (type != null && type == typeof(DataTable)) 336 | return CreateDataTable(o as Dictionary, null); 337 | #endif 338 | if (o is typedarray) 339 | { 340 | return ParseTypedArray(new Dictionary(), o); 341 | } 342 | if (o is IDictionary) 343 | { 344 | if (type != null && t == typeof(Dictionary<,>)) // deserialize a dictionary 345 | return RootDictionary(o, type); 346 | else // deserialize an object 347 | return ParseDictionary(o as Dictionary, null, type, null); 348 | } 349 | 350 | if (o is List) 351 | { 352 | if (type != null && t == typeof(Dictionary<,>)) // kv format 353 | return RootDictionary(o, type); 354 | 355 | if (type != null && t == typeof(List<>)) // deserialize to generic list 356 | return RootList(o, type); 357 | 358 | if (type == typeof(Hashtable)) 359 | return RootHashTable((List)o); 360 | else if (type == null) 361 | { 362 | List l = (List)o; 363 | if (l.Count > 0 && l[0].GetType() == typeof(Dictionary)) 364 | { 365 | Dictionary globals = new Dictionary(); 366 | List op = new List(); 367 | // try to get $types 368 | foreach (var i in l) 369 | op.Add(ParseDictionary((Dictionary)i, globals, null, null)); 370 | return op; 371 | } 372 | return l.ToArray(); 373 | } 374 | } 375 | else if (type != null && o.GetType() != type) 376 | return ChangeType(o, type); 377 | 378 | return o; 379 | } 380 | 381 | private object ChangeType(object o, Type type) 382 | { 383 | if (Reflection.Instance.IsTypeRegistered(type)) 384 | return Reflection.Instance.CreateCustom((string)o, type); 385 | else 386 | return o; 387 | } 388 | 389 | public object FillObject(object input, byte[] json) 390 | { 391 | _params.FixValues(); 392 | Dictionary ht = new BJsonParser(json, _params.UseUTCDateTime, _params.v1_4TypedArray).Decode() as Dictionary; 393 | if (ht == null) return null; 394 | return ParseDictionary(ht, null, input.GetType(), input); 395 | } 396 | 397 | private object RootHashTable(List o) 398 | { 399 | Hashtable h = new Hashtable(); 400 | 401 | foreach (Dictionary values in o) 402 | { 403 | object key = values["k"]; 404 | object val = values["v"]; 405 | if (key is Dictionary) 406 | key = ParseDictionary((Dictionary)key, null, typeof(object), null); 407 | 408 | if (val is Dictionary) 409 | val = ParseDictionary((Dictionary)val, null, typeof(object), null); 410 | 411 | h.Add(key, val); 412 | } 413 | 414 | return h; 415 | } 416 | 417 | private object RootList(object parse, Type type) 418 | { 419 | Type[] gtypes = Reflection.Instance.GetGenericArguments(type);// type.GetGenericArguments(); 420 | IList o = (IList)Reflection.Instance.FastCreateList(type, ((IList)parse).Count); 421 | Dictionary globals = new Dictionary(); 422 | 423 | foreach (var k in (IList)parse) 424 | { 425 | _globalTypes = false; 426 | object v = k; 427 | if (k is Dictionary) 428 | v = ParseDictionary(k as Dictionary, globals, gtypes[0], null); 429 | else 430 | v = k; 431 | 432 | o.Add(v); 433 | } 434 | return o; 435 | } 436 | 437 | private object RootDictionary(object parse, Type type) 438 | { 439 | Type[] gtypes = Reflection.Instance.GetGenericArguments(type); 440 | Type t1 = null; 441 | Type t2 = null; 442 | if (gtypes != null) 443 | { 444 | t1 = gtypes[0]; 445 | t2 = gtypes[1]; 446 | } 447 | var arraytype = t2.GetElementType(); 448 | 449 | if (parse is Dictionary) 450 | { 451 | IDictionary o = (IDictionary)Reflection.Instance.FastCreateInstance(type); 452 | 453 | foreach (var kv in (Dictionary)parse) 454 | { 455 | _globalTypes = false; 456 | object v; 457 | object k = kv.Key; 458 | if (t2.Name.StartsWith("Dictionary")) // deserialize a dictionary 459 | v = RootDictionary(kv.Value, t2); 460 | 461 | else if (kv.Value is Dictionary) 462 | v = ParseDictionary(kv.Value as Dictionary, null, t2, null); 463 | 464 | else if (t2 == typeof(byte[])) 465 | v = kv.Value; 466 | 467 | else if (gtypes != null && t2.IsArray) 468 | v = CreateArray((List)kv.Value, t2, arraytype, null); 469 | 470 | else if (kv.Value is IList) 471 | v = CreateGenericList((List)kv.Value, t2, t1, null); 472 | 473 | else 474 | v = kv.Value; 475 | 476 | o.Add(k, v); 477 | } 478 | 479 | return o; 480 | } 481 | if (parse is List) 482 | return CreateDictionary(parse as List, type, gtypes, null); 483 | 484 | return null; 485 | } 486 | 487 | private bool _globalTypes = false; 488 | private object ParseDictionary(Dictionary d, Dictionary globaltypes, Type type, object input) 489 | { 490 | object tn = ""; 491 | if (type == typeof(NameValueCollection)) 492 | return CreateNV(d); 493 | if (type == typeof(StringDictionary)) 494 | return CreateSD(d); 495 | 496 | if (d.TryGetValue("$i", out tn)) 497 | { 498 | object v = null; 499 | _cirrev.TryGetValue((int)tn, out v); 500 | return v; 501 | } 502 | 503 | if (d.TryGetValue("$types", out tn)) 504 | { 505 | _globalTypes = true; 506 | if (globaltypes == null) 507 | globaltypes = new Dictionary(); 508 | foreach (var kv in (Dictionary)tn) 509 | { 510 | globaltypes.Add((string)kv.Key, kv.Value); 511 | } 512 | } 513 | 514 | if (globaltypes != null) 515 | _globalTypes = true; 516 | 517 | bool found = d.TryGetValue("$type", out tn); 518 | #if !SILVERLIGHT 519 | if (found == false && type == typeof(System.Object)) 520 | { 521 | return d; // CreateDataset(d, globaltypes); 522 | } 523 | #endif 524 | if (found) 525 | { 526 | if (_globalTypes && globaltypes != null) 527 | { 528 | object tname = ""; 529 | if (globaltypes != null && globaltypes.TryGetValue((string)tn, out tname)) 530 | tn = tname; 531 | } 532 | type = Reflection.Instance.GetTypeFromCache((string)tn, true); 533 | } 534 | 535 | if (type == null) 536 | throw new Exception("Cannot determine type"); 537 | 538 | string typename = type.FullName; 539 | object o = input; 540 | if (o == null) 541 | { 542 | if (_params.ParametricConstructorOverride) 543 | o = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type); 544 | else 545 | o = Reflection.Instance.FastCreateInstance(type); 546 | } 547 | 548 | int circount = 0; 549 | if (_circobj.TryGetValue(o, out circount) == false) 550 | { 551 | circount = _circobj.Count + 1; 552 | _circobj.Add(o, circount); 553 | _cirrev.Add(circount, o); 554 | } 555 | 556 | Dictionary props = Reflection.Instance.Getproperties(type, typename, _params.ShowReadOnlyProperties);//, Reflection.Instance.IsTypeRegistered(type)); 557 | foreach (var kv in d) 558 | { 559 | var n = kv.Key; 560 | var v = kv.Value; 561 | string name = n.ToLowerInvariant(); 562 | myPropInfo pi; 563 | if (props.TryGetValue(name, out pi) == false) 564 | continue; 565 | if (pi.CanWrite) 566 | { 567 | //object v = d[n]; 568 | 569 | if (v != null) 570 | { 571 | object oset = v; 572 | if (v is typedarray) 573 | { 574 | oset = ParseTypedArray(globaltypes, v); 575 | } 576 | else 577 | { 578 | switch (pi.Type) 579 | { 580 | #if !SILVERLIGHT 581 | case myPropInfoType.DataSet: 582 | oset = CreateDataset((Dictionary)v, globaltypes); 583 | break; 584 | case myPropInfoType.DataTable: 585 | oset = CreateDataTable((Dictionary)v, globaltypes); 586 | break; 587 | #endif 588 | case myPropInfoType.Custom: 589 | oset = Reflection.Instance.CreateCustom((string)v, pi.pt); 590 | break; 591 | case myPropInfoType.Enum: 592 | oset = CreateEnum(pi.pt, v); 593 | break; 594 | case myPropInfoType.StringKeyDictionary: 595 | oset = CreateStringKeyDictionary((Dictionary)v, pi.pt, pi.GenericTypes, globaltypes); 596 | break; 597 | case myPropInfoType.Hashtable: 598 | case myPropInfoType.Dictionary: 599 | oset = CreateDictionary((List)v, pi.pt, pi.GenericTypes, globaltypes); 600 | break; 601 | case myPropInfoType.NameValue: oset = CreateNV((Dictionary)v); break; 602 | case myPropInfoType.StringDictionary: oset = CreateSD((Dictionary)v); break; 603 | case myPropInfoType.Array: 604 | oset = CreateArray((List)v, pi.pt, pi.bt, globaltypes); 605 | break; 606 | default: 607 | { 608 | if (pi.IsGenericType && pi.IsValueType == false) 609 | oset = CreateGenericList((List)v, pi.pt, pi.bt, globaltypes); 610 | else if ((pi.IsClass || pi.IsStruct || pi.IsInterface) && v is Dictionary) 611 | { 612 | var oo = (Dictionary)v; 613 | if (oo.ContainsKey("$schema")) 614 | oset = CreateDataset(oo, globaltypes); 615 | else 616 | oset = ParseDictionary(oo, globaltypes, pi.pt, input); 617 | } 618 | else if (v is List) 619 | oset = CreateArray((List)v, pi.pt, typeof(object), globaltypes); 620 | break; 621 | } 622 | } 623 | } 624 | o = pi.setter(o, oset); 625 | } 626 | } 627 | } 628 | return o; 629 | } 630 | 631 | private object ParseTypedArray(Dictionary globaltypes, object v) 632 | { 633 | object oset; 634 | var ta = (typedarray)v; 635 | var t = Reflection.Instance.GetTypeFromCache(ta.typename, true); 636 | IList a = Array.CreateInstance(t, ta.count); 637 | int i = 0; 638 | foreach (var dd in ta.data) 639 | { 640 | object oo = null; 641 | if (dd == null) 642 | oo = null; 643 | else if (dd is typedarray) 644 | oo = ParseTypedArray(globaltypes, dd); 645 | else if (dd is Dictionary) 646 | oo = ParseDictionary((Dictionary)dd, globaltypes, t, null); 647 | else if (dd is List) 648 | oo = CreateArray((List)dd, t, t.GetElementType(), globaltypes); 649 | else 650 | oo = dd; 651 | a[i++] = oo; 652 | } 653 | oset = a; 654 | return oset; 655 | } 656 | 657 | private StringDictionary CreateSD(Dictionary d) 658 | { 659 | StringDictionary nv = new StringDictionary(); 660 | 661 | foreach (var o in d) 662 | nv.Add(o.Key, (string)o.Value); 663 | 664 | return nv; 665 | } 666 | 667 | private NameValueCollection CreateNV(Dictionary d) 668 | { 669 | NameValueCollection nv = new NameValueCollection(); 670 | 671 | foreach (var o in d) 672 | nv.Add(o.Key, (string)o.Value); 673 | 674 | return nv; 675 | } 676 | 677 | private object CreateEnum(Type pt, object v) 678 | { 679 | // FEATURE : optimize create enum 680 | #if !SILVERLIGHT 681 | return Enum.Parse(pt, v.ToString()); 682 | #else 683 | return Enum.Parse(pt, v, true); 684 | #endif 685 | } 686 | 687 | private object CreateArray(List data, Type pt, Type bt, Dictionary globalTypes) 688 | { 689 | if (bt == null) 690 | bt = typeof(object); 691 | 692 | Array col = Array.CreateInstance(bt, data.Count); 693 | var arraytype = bt.GetElementType(); 694 | // create an array of objects 695 | for (int i = 0; i < data.Count; i++)// each (object ob in data) 696 | { 697 | object ob = data[i]; 698 | if (ob == null) 699 | { 700 | continue; 701 | } 702 | if (ob is IDictionary) 703 | col.SetValue(ParseDictionary((Dictionary)ob, globalTypes, bt, null), i); 704 | else if (ob is ICollection) 705 | col.SetValue(CreateArray((List)ob, bt, arraytype, globalTypes), i); 706 | else 707 | col.SetValue(ob, i); 708 | } 709 | 710 | return col; 711 | } 712 | 713 | private object CreateGenericList(List data, Type pt, Type bt, Dictionary globalTypes) 714 | { 715 | if (pt != typeof(object)) 716 | { 717 | IList col = (IList)Reflection.Instance.FastCreateList(pt, data.Count); 718 | // create an array of objects 719 | foreach (object ob in data) 720 | { 721 | if (ob is IDictionary) 722 | col.Add(ParseDictionary((Dictionary)ob, globalTypes, bt, null)); 723 | 724 | else if (ob is List) 725 | { 726 | if (bt.IsGenericType) 727 | col.Add((List)ob); 728 | else 729 | col.Add(((List)ob).ToArray()); 730 | } 731 | else if (ob is typedarray) 732 | col.Add(((typedarray)ob).data.ToArray()); 733 | else 734 | col.Add(ob); 735 | } 736 | return col; 737 | } 738 | return data; 739 | } 740 | 741 | private object CreateStringKeyDictionary(Dictionary reader, Type pt, Type[] types, Dictionary globalTypes) 742 | { 743 | var col = (IDictionary)Reflection.Instance.FastCreateInstance(pt); 744 | Type arraytype = null; 745 | Type t2 = null; 746 | if (types != null) 747 | t2 = types[1]; 748 | 749 | Type generictype = null; 750 | var ga = Reflection.Instance.GetGenericArguments(t2); 751 | if (ga.Length > 0) 752 | generictype = ga[0]; 753 | arraytype = t2.GetElementType(); 754 | 755 | foreach (KeyValuePair values in reader) 756 | { 757 | var key = values.Key; 758 | object val = null; 759 | 760 | if (values.Value is Dictionary) 761 | val = ParseDictionary((Dictionary)values.Value, globalTypes, t2, null); 762 | 763 | else if (types != null && t2.IsArray) 764 | { 765 | if (values.Value is Array) 766 | val = values.Value; 767 | else 768 | val = CreateArray((List)values.Value, t2, arraytype, globalTypes); 769 | } 770 | else if (values.Value is IList) 771 | val = CreateGenericList((List)values.Value, t2, generictype, globalTypes); 772 | 773 | else 774 | val = values.Value; 775 | 776 | col.Add(key, val); 777 | } 778 | 779 | return col; 780 | } 781 | 782 | private object CreateDictionary(List reader, Type pt, Type[] types, Dictionary globalTypes) 783 | { 784 | IDictionary col = (IDictionary)Reflection.Instance.FastCreateInstance(pt); 785 | Type t1 = null; 786 | Type t2 = null; 787 | if (types != null) 788 | { 789 | t1 = types[0]; 790 | t2 = types[1]; 791 | } 792 | 793 | foreach (Dictionary values in reader) 794 | { 795 | object key = values["k"]; 796 | object val = values["v"]; 797 | 798 | if (key is Dictionary) 799 | key = ParseDictionary((Dictionary)key, globalTypes, t1, null); 800 | 801 | if (typeof(IDictionary).IsAssignableFrom(t2)) 802 | val = RootDictionary(val, t2); 803 | 804 | else if (val is Dictionary) 805 | val = ParseDictionary((Dictionary)val, globalTypes, t2, null); 806 | 807 | col.Add(key, val); 808 | } 809 | 810 | return col; 811 | } 812 | 813 | #if !SILVERLIGHT 814 | private DataSet CreateDataset(Dictionary reader, Dictionary globalTypes) 815 | { 816 | DataSet ds = new DataSet(); 817 | ds.EnforceConstraints = false; 818 | ds.BeginInit(); 819 | 820 | // read dataset schema here 821 | var schema = reader["$schema"]; 822 | 823 | if (schema is string) 824 | { 825 | TextReader tr = new StringReader((string)schema); 826 | ds.ReadXmlSchema(tr); 827 | } 828 | else 829 | { 830 | DatasetSchema ms = (DatasetSchema)ParseDictionary((Dictionary)schema, globalTypes, typeof(DatasetSchema), null); 831 | ds.DataSetName = ms.Name; 832 | for (int i = 0; i < ms.Info.Count; i += 3) 833 | { 834 | if (ds.Tables.Contains(ms.Info[i]) == false) 835 | ds.Tables.Add(ms.Info[i]); 836 | ds.Tables[ms.Info[i]].Columns.Add(ms.Info[i + 1], Type.GetType(ms.Info[i + 2])); 837 | } 838 | } 839 | 840 | foreach (KeyValuePair pair in reader) 841 | { 842 | if (pair.Key == "$type" || pair.Key == "$schema") continue; 843 | 844 | List rows = (List)pair.Value; 845 | if (rows == null) continue; 846 | 847 | DataTable dt = ds.Tables[pair.Key]; 848 | ReadDataTable(rows, dt); 849 | } 850 | 851 | ds.EndInit(); 852 | 853 | return ds; 854 | } 855 | 856 | private void ReadDataTable(List rows, DataTable dt) 857 | { 858 | dt.BeginInit(); 859 | dt.BeginLoadData(); 860 | 861 | foreach (List row in rows) 862 | { 863 | object[] v = new object[row.Count]; 864 | row.CopyTo(v, 0); 865 | dt.Rows.Add(v); 866 | } 867 | 868 | dt.EndLoadData(); 869 | dt.EndInit(); 870 | } 871 | 872 | DataTable CreateDataTable(Dictionary reader, Dictionary globalTypes) 873 | { 874 | var dt = new DataTable(); 875 | 876 | // read dataset schema here 877 | var schema = reader["$schema"]; 878 | 879 | if (schema is string) 880 | { 881 | TextReader tr = new StringReader((string)schema); 882 | dt.ReadXmlSchema(tr); 883 | } 884 | else 885 | { 886 | var ms = (DatasetSchema)this.ParseDictionary((Dictionary)schema, globalTypes, typeof(DatasetSchema), null); 887 | dt.TableName = ms.Info[0]; 888 | for (int i = 0; i < ms.Info.Count; i += 3) 889 | { 890 | dt.Columns.Add(ms.Info[i + 1], Type.GetType(ms.Info[i + 2])); 891 | } 892 | } 893 | 894 | foreach (var pair in reader) 895 | { 896 | if (pair.Key == "$type" || pair.Key == "$schema") 897 | continue; 898 | 899 | var rows = (List)pair.Value; 900 | if (rows == null) 901 | continue; 902 | 903 | if (!dt.TableName.Equals(pair.Key, StringComparison.InvariantCultureIgnoreCase)) 904 | continue; 905 | 906 | ReadDataTable(rows, dt); 907 | } 908 | 909 | return dt; 910 | } 911 | #endif 912 | } 913 | 914 | } -------------------------------------------------------------------------------- /fastBinaryJSON/BJsonParser.cs: -------------------------------------------------------------------------------- 1 | using fastJSON; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace fastBinaryJSON 6 | { 7 | internal sealed class BJsonParser 8 | { 9 | readonly byte[] _json; 10 | int _index; 11 | bool _useUTC = true; 12 | bool _v1_4TA = false; 13 | 14 | internal BJsonParser(byte[] json, bool useUTC, bool v1_4TA) 15 | { 16 | this._json = json; 17 | _v1_4TA = v1_4TA; 18 | _useUTC = useUTC; 19 | } 20 | 21 | public object Decode() 22 | { 23 | bool b = false; 24 | return ParseValue(out b); 25 | } 26 | 27 | private Dictionary ParseObject() 28 | { 29 | Dictionary dic = new Dictionary(10); 30 | bool breakparse = false; 31 | while (!breakparse) 32 | { 33 | byte t = GetToken(); 34 | if (t == TOKENS.COMMA) 35 | continue; 36 | if (t == TOKENS.DOC_END) 37 | break; 38 | if (t == TOKENS.TYPES_POINTER) 39 | { 40 | // save curr index position 41 | int savedindex = _index; 42 | // set index = pointer 43 | _index = ParseInt(); 44 | t = GetToken(); 45 | // read $types 46 | breakparse = readkeyvalue(dic, ref t); 47 | // set index = saved + 4 48 | _index = savedindex + 4; 49 | } 50 | else 51 | breakparse = readkeyvalue(dic, ref t); 52 | } 53 | return dic; 54 | } 55 | 56 | private bool readkeyvalue(Dictionary dic, ref byte t) 57 | { 58 | bool breakparse; 59 | string key = ""; 60 | //if (t != TOKENS.NAME) 61 | if (t == TOKENS.NAME) 62 | key = ParseName(); 63 | else if (t == TOKENS.NAME_UNI) 64 | key = ParseName2(); 65 | else 66 | throw new Exception("excpecting a name field"); 67 | 68 | t = GetToken(); 69 | if (t != TOKENS.COLON) 70 | throw new Exception("expecting a colon"); 71 | object val = ParseValue(out breakparse); 72 | 73 | if (breakparse == false) 74 | dic.Add(key, val); 75 | 76 | return breakparse; 77 | } 78 | 79 | private string ParseName2() // unicode byte len string -> <128 len chars 80 | { 81 | byte c = _json[_index++]; 82 | string s = Reflection.UnicodeGetString(_json, _index, c); 83 | _index += c; 84 | return s; 85 | } 86 | 87 | private string ParseName() 88 | { 89 | byte c = _json[_index++]; 90 | string s = Reflection.UTF8GetString(_json, _index, c); 91 | _index += c; 92 | return s; 93 | } 94 | 95 | private List ParseArray() 96 | { 97 | List array = new List(); 98 | 99 | bool breakparse = false; 100 | while (!breakparse) 101 | { 102 | object o = ParseValue(out breakparse); 103 | byte t = 0; 104 | if (breakparse == false) 105 | { 106 | array.Add(o); 107 | t = GetToken(); 108 | } 109 | else t = (byte)o; 110 | 111 | if (t == TOKENS.COMMA) 112 | continue; 113 | if (t == TOKENS.ARRAY_END) 114 | break; 115 | } 116 | return array; 117 | } 118 | 119 | private object ParseValue(out bool breakparse) 120 | { 121 | byte t = GetToken(); 122 | breakparse = false; 123 | switch (t) 124 | { 125 | case TOKENS.BYTE: 126 | return ParseByte(); 127 | case TOKENS.BYTEARRAY: 128 | return ParseByteArray(); 129 | case TOKENS.CHAR: 130 | return ParseChar(); 131 | case TOKENS.DATETIME: 132 | return ParseDateTime(); 133 | case TOKENS.DECIMAL: 134 | return ParseDecimal(); 135 | case TOKENS.DOUBLE: 136 | return ParseDouble(); 137 | case TOKENS.FLOAT: 138 | return ParseFloat(); 139 | case TOKENS.GUID: 140 | return ParseGuid(); 141 | case TOKENS.INT: 142 | return ParseInt(); 143 | case TOKENS.LONG: 144 | return ParseLong(); 145 | case TOKENS.SHORT: 146 | return ParseShort(); 147 | case TOKENS.UINT: 148 | return ParseUint(); 149 | case TOKENS.ULONG: 150 | return ParseULong(); 151 | case TOKENS.USHORT: 152 | return ParseUShort(); 153 | case TOKENS.UNICODE_STRING: 154 | return ParseUnicodeString(); 155 | case TOKENS.STRING: 156 | return ParseString(); 157 | case TOKENS.DOC_START: 158 | return ParseObject(); 159 | case TOKENS.ARRAY_START: 160 | return ParseArray(); 161 | case TOKENS.TRUE: 162 | return true; 163 | case TOKENS.FALSE: 164 | return false; 165 | case TOKENS.NULL: 166 | return null; 167 | case TOKENS.ARRAY_END: 168 | breakparse = true; 169 | return TOKENS.ARRAY_END; 170 | case TOKENS.DOC_END: 171 | breakparse = true; 172 | return TOKENS.DOC_END; 173 | case TOKENS.COMMA: 174 | breakparse = true; 175 | return TOKENS.COMMA; 176 | case TOKENS.ARRAY_TYPED: 177 | case TOKENS.ARRAY_TYPED_LONG: 178 | return ParseTypedArray(t); 179 | case TOKENS.TIMESPAN: 180 | return ParsTimeSpan(); 181 | } 182 | 183 | throw new Exception("Unrecognized token at index = " + _index); 184 | } 185 | 186 | private TimeSpan ParsTimeSpan() 187 | { 188 | long l = Helper.ToInt64(_json, _index); 189 | _index += 8; 190 | 191 | TimeSpan dt = new TimeSpan(l); 192 | 193 | return dt; 194 | } 195 | 196 | private object ParseTypedArray(byte token) 197 | { 198 | typedarray ar = new typedarray(); 199 | if (token == TOKENS.ARRAY_TYPED) 200 | { 201 | if (_v1_4TA) 202 | ar.typename = ParseName(); 203 | else 204 | ar.typename = ParseName2(); 205 | } 206 | else 207 | ar.typename = ParseNameLong(); 208 | 209 | ar.count = ParseInt(); 210 | 211 | bool breakparse = false; 212 | while (!breakparse) 213 | { 214 | object o = ParseValue(out breakparse); 215 | byte b = 0; 216 | if (breakparse == false) 217 | { 218 | ar.data.Add(o); 219 | b = GetToken(); 220 | } 221 | else b = (byte)o; 222 | 223 | if (b == TOKENS.COMMA) 224 | continue; 225 | if (b == TOKENS.ARRAY_END) 226 | break; 227 | } 228 | return ar; 229 | } 230 | 231 | private string ParseNameLong() // unicode short len string -> <32k chars 232 | { 233 | short c = Helper.ToInt16(_json, _index); 234 | _index += 2; 235 | string s = Reflection.UnicodeGetString(_json, _index, c); 236 | _index += c; 237 | return s; 238 | } 239 | 240 | private object ParseChar() 241 | { 242 | short u = Helper.ToInt16(_json, _index); 243 | _index += 2; 244 | return u; 245 | } 246 | 247 | private Guid ParseGuid() 248 | { 249 | byte[] b = new byte[16]; 250 | Buffer.BlockCopy(_json, _index, b, 0, 16); 251 | _index += 16; 252 | return new Guid(b); 253 | } 254 | 255 | private float ParseFloat() 256 | { 257 | float f = BitConverter.ToSingle(_json, _index); 258 | _index += 4; 259 | return f; 260 | } 261 | 262 | private ushort ParseUShort() 263 | { 264 | ushort u = (ushort)Helper.ToInt16(_json, _index); 265 | _index += 2; 266 | return u; 267 | } 268 | 269 | private ulong ParseULong() 270 | { 271 | ulong u = (ulong)Helper.ToInt64(_json, _index); 272 | _index += 8; 273 | return u; 274 | } 275 | 276 | private uint ParseUint() 277 | { 278 | uint u = (uint)Helper.ToInt32(_json, _index); 279 | _index += 4; 280 | return u; 281 | } 282 | 283 | private short ParseShort() 284 | { 285 | short u = (short)Helper.ToInt16(_json, _index); 286 | _index += 2; 287 | return u; 288 | } 289 | 290 | private long ParseLong() 291 | { 292 | long u = (long)Helper.ToInt64(_json, _index); 293 | _index += 8; 294 | return u; 295 | } 296 | 297 | private int ParseInt() 298 | { 299 | int u = (int)Helper.ToInt32(_json, _index); 300 | _index += 4; 301 | return u; 302 | } 303 | 304 | private double ParseDouble() 305 | { 306 | double d = BitConverter.ToDouble(_json, _index); 307 | _index += 8; 308 | return d; 309 | } 310 | 311 | private object ParseUnicodeString() 312 | { 313 | int c = Helper.ToInt32(_json, _index); 314 | _index += 4; 315 | 316 | string s = Reflection.UnicodeGetString(_json, _index, c); 317 | _index += c; 318 | return s; 319 | } 320 | 321 | private string ParseString() 322 | { 323 | int c = Helper.ToInt32(_json, _index); 324 | _index += 4; 325 | 326 | string s = Reflection.UTF8GetString(_json, _index, c); 327 | _index += c; 328 | return s; 329 | } 330 | 331 | private decimal ParseDecimal() 332 | { 333 | int[] i = new int[4]; 334 | i[0] = Helper.ToInt32(_json, _index); 335 | _index += 4; 336 | i[1] = Helper.ToInt32(_json, _index); 337 | _index += 4; 338 | i[2] = Helper.ToInt32(_json, _index); 339 | _index += 4; 340 | i[3] = Helper.ToInt32(_json, _index); 341 | _index += 4; 342 | 343 | return new decimal(i); 344 | } 345 | 346 | private DateTime ParseDateTime() 347 | { 348 | long l = Helper.ToInt64(_json, _index); 349 | _index += 8; 350 | 351 | DateTime dt = new DateTime(l); 352 | if (_useUTC) 353 | dt = dt.ToLocalTime(); // to local time 354 | 355 | return dt; 356 | } 357 | 358 | private byte[] ParseByteArray() 359 | { 360 | int c = Helper.ToInt32(_json, _index); 361 | _index += 4; 362 | byte[] b = new byte[c]; 363 | Buffer.BlockCopy(_json, _index, b, 0, c); 364 | _index += c; 365 | return b; 366 | } 367 | 368 | private byte ParseByte() 369 | { 370 | return _json[_index++]; 371 | } 372 | 373 | private byte GetToken() 374 | { 375 | byte b = _json[_index++]; 376 | return b; 377 | } 378 | } 379 | } 380 | -------------------------------------------------------------------------------- /fastBinaryJSON/BJsonSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | #if !SILVERLIGHT 5 | using System.Data; 6 | #endif 7 | using System.IO; 8 | using System.Collections.Specialized; 9 | using fastJSON; 10 | 11 | namespace fastBinaryJSON 12 | { 13 | internal sealed class BJSONSerializer : IDisposable 14 | { 15 | private MemoryStream _output = new MemoryStream(); 16 | //private MemoryStream _before = new MemoryStream(); 17 | private int _typespointer = 0; 18 | private int _MAX_DEPTH = 20; 19 | int _current_depth = 0; 20 | private Dictionary _globalTypes = new Dictionary(); 21 | private Dictionary _cirobj = new Dictionary(); 22 | private BJSONParameters _params; 23 | 24 | private void Dispose(bool disposing) 25 | { 26 | if (disposing) 27 | { 28 | // dispose managed resources 29 | _output.Close(); 30 | //_before.Close(); 31 | } 32 | // free native resources 33 | } 34 | 35 | public void Dispose() 36 | { 37 | Dispose(true); 38 | GC.SuppressFinalize(this); 39 | } 40 | 41 | internal BJSONSerializer(BJSONParameters param) 42 | { 43 | _params = param; 44 | _MAX_DEPTH = param.SerializerMaxDepth; 45 | } 46 | 47 | internal byte[] ConvertToBJSON(object obj) 48 | { 49 | WriteValue(obj); 50 | 51 | // add $types 52 | if (_params.UsingGlobalTypes && _globalTypes != null && _globalTypes.Count > 0) 53 | { 54 | var pointer = (int)_output.Length; 55 | WriteName("$types"); 56 | WriteColon(); 57 | WriteTypes(_globalTypes); 58 | //var i = _output.Length; 59 | _output.Seek(_typespointer, SeekOrigin.Begin); 60 | _output.Write(Helper.GetBytes(pointer, false), 0, 4); 61 | 62 | return _output.ToArray(); 63 | } 64 | 65 | return _output.ToArray(); 66 | } 67 | 68 | private void WriteTypes(Dictionary dic) 69 | { 70 | _output.WriteByte(TOKENS.DOC_START); 71 | 72 | bool pendingSeparator = false; 73 | 74 | foreach (var entry in dic) 75 | { 76 | if (pendingSeparator) WriteComma(); 77 | 78 | WritePair(entry.Value.ToString(), entry.Key); 79 | 80 | pendingSeparator = true; 81 | } 82 | _output.WriteByte(TOKENS.DOC_END); 83 | } 84 | 85 | private void WriteValue(object obj) 86 | { 87 | if (obj == null || obj is DBNull) 88 | WriteNull(); 89 | 90 | else if (obj is string) 91 | WriteString((string)obj); 92 | 93 | else if (obj is char) 94 | WriteChar((char)obj); 95 | 96 | else if (obj is Guid) 97 | WriteGuid((Guid)obj); 98 | 99 | else if (obj is bool) 100 | WriteBool((bool)obj); 101 | 102 | else if (obj is int) 103 | WriteInt((int)obj); 104 | 105 | else if (obj is uint) 106 | WriteUInt((uint)obj); 107 | 108 | else if (obj is long) 109 | WriteLong((long)obj); 110 | 111 | else if (obj is ulong) 112 | WriteULong((ulong)obj); 113 | 114 | else if (obj is decimal) 115 | WriteDecimal((decimal)obj); 116 | 117 | else if (obj is sbyte) 118 | WriteSByte((sbyte)obj); 119 | 120 | else if (obj is byte) 121 | WriteByte((byte)obj); 122 | 123 | else if (obj is double) 124 | WriteDouble((double)obj); 125 | 126 | else if (obj is float) 127 | WriteFloat((float)obj); 128 | 129 | else if (obj is short) 130 | WriteShort((short)obj); 131 | 132 | else if (obj is ushort) 133 | WriteUShort((ushort)obj); 134 | 135 | else if (obj is DateTime) 136 | WriteDateTime((DateTime)obj); 137 | 138 | else if (obj is TimeSpan) 139 | WriteTimeSpan((TimeSpan)obj); 140 | #if NET4 141 | else if (obj is System.Dynamic.ExpandoObject) 142 | WriteStringDictionary((IDictionary)obj); 143 | #endif 144 | 145 | else if (obj is IDictionary && obj.GetType().IsGenericType && obj.GetType().GetGenericArguments()[0] == typeof(string)) 146 | WriteStringDictionary((IDictionary)obj); 147 | 148 | else if (obj is IDictionary) 149 | WriteDictionary((IDictionary)obj); 150 | #if !SILVERLIGHT 151 | else if (obj is DataSet) 152 | WriteDataset((DataSet)obj); 153 | 154 | else if (obj is DataTable) 155 | WriteDataTable((DataTable)obj); 156 | #endif 157 | else if (obj is byte[]) 158 | WriteBytes((byte[])obj); 159 | 160 | else if (obj is StringDictionary) 161 | WriteSD((StringDictionary)obj); 162 | 163 | else if (obj is NameValueCollection) 164 | WriteNV((NameValueCollection)obj); 165 | 166 | else if (_params.UseTypedArrays && obj is Array) 167 | WriteTypedArray((ICollection)obj); 168 | 169 | else if (obj is IEnumerable) 170 | WriteArray((IEnumerable)obj); 171 | 172 | else if (obj is Enum) 173 | WriteEnum((Enum)obj); 174 | 175 | else if (Reflection.Instance.IsTypeRegistered(obj.GetType())) 176 | WriteCustom(obj); 177 | 178 | else 179 | WriteObject(obj); 180 | } 181 | 182 | private void WriteSByte(sbyte p) 183 | { 184 | _output.WriteByte(TOKENS.BYTE); 185 | byte i = (byte)p; 186 | _output.WriteByte(i); 187 | } 188 | 189 | private void WriteTimeSpan(TimeSpan obj) 190 | { 191 | _output.WriteByte(TOKENS.TIMESPAN); 192 | byte[] b = Helper.GetBytes(obj.Ticks, false); 193 | _output.Write(b, 0, b.Length); 194 | } 195 | 196 | private void WriteTypedArray(ICollection array) 197 | { 198 | bool pendingSeperator = false; 199 | bool token = true; 200 | var t = array.GetType(); 201 | if (t.IsGenericType == false)// != null) // non generic array 202 | { 203 | //if (t.GetElementType().IsClass) 204 | { 205 | token = false; 206 | byte[] b; 207 | // array type name 208 | if (_params.v1_4TypedArray) 209 | b = Reflection.UTF8GetBytes(Reflection.Instance.GetTypeAssemblyName(t.GetElementType())); 210 | else 211 | b = Reflection.UnicodeGetBytes(Reflection.Instance.GetTypeAssemblyName(t.GetElementType())); 212 | if (b.Length < 256) 213 | { 214 | _output.WriteByte(TOKENS.ARRAY_TYPED); 215 | _output.WriteByte((byte)b.Length); 216 | _output.Write(b, 0, b.Length); 217 | } 218 | else 219 | { 220 | _output.WriteByte(TOKENS.ARRAY_TYPED_LONG); 221 | _output.Write(Helper.GetBytes(b.Length, false), 0, 2); 222 | _output.Write(b, 0, b.Length); 223 | } 224 | // array count 225 | _output.Write(Helper.GetBytes(array.Count, false), 0, 4); //count 226 | } 227 | } 228 | if (token) 229 | _output.WriteByte(TOKENS.ARRAY_START); 230 | 231 | foreach (object obj in array) 232 | { 233 | if (pendingSeperator) WriteComma(); 234 | 235 | WriteValue(obj); 236 | 237 | pendingSeperator = true; 238 | } 239 | _output.WriteByte(TOKENS.ARRAY_END); 240 | } 241 | 242 | private void WriteNV(NameValueCollection nameValueCollection) 243 | { 244 | _output.WriteByte(TOKENS.DOC_START); 245 | 246 | bool pendingSeparator = false; 247 | 248 | foreach (string key in nameValueCollection) 249 | { 250 | if (pendingSeparator) _output.WriteByte(TOKENS.COMMA); 251 | 252 | WritePair(key, nameValueCollection[key]); 253 | 254 | pendingSeparator = true; 255 | } 256 | _output.WriteByte(TOKENS.DOC_END); 257 | } 258 | 259 | private void WriteSD(StringDictionary stringDictionary) 260 | { 261 | _output.WriteByte(TOKENS.DOC_START); 262 | 263 | bool pendingSeparator = false; 264 | 265 | foreach (DictionaryEntry entry in stringDictionary) 266 | { 267 | if (pendingSeparator) _output.WriteByte(TOKENS.COMMA); 268 | 269 | WritePair((string)entry.Key, entry.Value); 270 | 271 | pendingSeparator = true; 272 | } 273 | _output.WriteByte(TOKENS.DOC_END); 274 | } 275 | 276 | private void WriteUShort(ushort p) 277 | { 278 | _output.WriteByte(TOKENS.USHORT); 279 | _output.Write(Helper.GetBytes(p, false), 0, 2); 280 | } 281 | 282 | private void WriteShort(short p) 283 | { 284 | _output.WriteByte(TOKENS.SHORT); 285 | _output.Write(Helper.GetBytes(p, false), 0, 2); 286 | } 287 | 288 | private void WriteFloat(float p) 289 | { 290 | _output.WriteByte(TOKENS.FLOAT); 291 | byte[] b = BitConverter.GetBytes(p); 292 | _output.Write(b, 0, b.Length); 293 | } 294 | 295 | private void WriteDouble(double p) 296 | { 297 | _output.WriteByte(TOKENS.DOUBLE); 298 | var b = BitConverter.GetBytes(p); 299 | _output.Write(b, 0, b.Length); 300 | } 301 | 302 | private void WriteByte(byte p) 303 | { 304 | _output.WriteByte(TOKENS.BYTE); 305 | _output.WriteByte(p); 306 | } 307 | 308 | private void WriteDecimal(decimal p) 309 | { 310 | _output.WriteByte(TOKENS.DECIMAL); 311 | var b = decimal.GetBits(p); 312 | foreach (var c in b) 313 | _output.Write(Helper.GetBytes(c, false), 0, 4); 314 | } 315 | 316 | private void WriteULong(ulong p) 317 | { 318 | _output.WriteByte(TOKENS.ULONG); 319 | _output.Write(Helper.GetBytes((long)p, false), 0, 8); 320 | } 321 | 322 | private void WriteUInt(uint p) 323 | { 324 | _output.WriteByte(TOKENS.UINT); 325 | _output.Write(Helper.GetBytes(p, false), 0, 4); 326 | } 327 | 328 | private void WriteLong(long p) 329 | { 330 | _output.WriteByte(TOKENS.LONG); 331 | _output.Write(Helper.GetBytes(p, false), 0, 8); 332 | } 333 | 334 | private void WriteChar(char p) 335 | { 336 | _output.WriteByte(TOKENS.CHAR); 337 | _output.Write(Helper.GetBytes((short)p, false), 0, 2); 338 | } 339 | 340 | private void WriteBytes(byte[] p) 341 | { 342 | _output.WriteByte(TOKENS.BYTEARRAY); 343 | _output.Write(Helper.GetBytes(p.Length, false), 0, 4); 344 | _output.Write(p, 0, p.Length); 345 | } 346 | 347 | private void WriteBool(bool p) 348 | { 349 | if (p) 350 | _output.WriteByte(TOKENS.TRUE); 351 | else 352 | _output.WriteByte(TOKENS.FALSE); 353 | } 354 | 355 | private void WriteNull() 356 | { 357 | _output.WriteByte(TOKENS.NULL); 358 | } 359 | 360 | 361 | private void WriteCustom(object obj) 362 | { 363 | Reflection.Serialize s; 364 | Reflection.Instance._customSerializer.TryGetValue(obj.GetType(), out s); 365 | WriteString(s(obj)); 366 | } 367 | 368 | private void WriteColon() 369 | { 370 | _output.WriteByte(TOKENS.COLON); 371 | } 372 | 373 | private void WriteComma() 374 | { 375 | _output.WriteByte(TOKENS.COMMA); 376 | } 377 | 378 | private void WriteEnum(Enum e) 379 | { 380 | WriteString(e.ToString()); 381 | } 382 | 383 | private void WriteInt(int i) 384 | { 385 | //if (_params.OptimizeSize) 386 | //{ 387 | // if (i < 256) 388 | // { 389 | // WriteByte((byte)i); 390 | // return; 391 | // } 392 | // else if (i < 65536) 393 | // { 394 | // WriteUShort((ushort)i); 395 | // return; 396 | // } 397 | //} 398 | _output.WriteByte(TOKENS.INT); 399 | _output.Write(Helper.GetBytes(i, false), 0, 4); 400 | } 401 | 402 | private void WriteGuid(Guid g) 403 | { 404 | _output.WriteByte(TOKENS.GUID); 405 | _output.Write(g.ToByteArray(), 0, 16); 406 | } 407 | 408 | private void WriteDateTime(DateTime dateTime) 409 | { 410 | DateTime dt = dateTime; 411 | if (_params.UseUTCDateTime) 412 | dt = dateTime.ToUniversalTime(); 413 | 414 | _output.WriteByte(TOKENS.DATETIME); 415 | byte[] b = Helper.GetBytes(dt.Ticks, false); 416 | _output.Write(b, 0, b.Length); 417 | } 418 | 419 | #if !SILVERLIGHT 420 | private DatasetSchema GetSchema(DataTable ds) 421 | { 422 | if (ds == null) return null; 423 | 424 | DatasetSchema m = new DatasetSchema(); 425 | m.Info = new List(); 426 | m.Name = ds.TableName; 427 | 428 | foreach (DataColumn c in ds.Columns) 429 | { 430 | m.Info.Add(ds.TableName); 431 | m.Info.Add(c.ColumnName); 432 | m.Info.Add(c.DataType.ToString()); 433 | } 434 | // FEATURE : serialize relations and constraints here 435 | 436 | return m; 437 | } 438 | 439 | private DatasetSchema GetSchema(DataSet ds) 440 | { 441 | if (ds == null) return null; 442 | 443 | DatasetSchema m = new DatasetSchema(); 444 | m.Info = new List(); 445 | m.Name = ds.DataSetName; 446 | 447 | foreach (DataTable t in ds.Tables) 448 | { 449 | foreach (DataColumn c in t.Columns) 450 | { 451 | m.Info.Add(t.TableName); 452 | m.Info.Add(c.ColumnName); 453 | m.Info.Add(c.DataType.ToString()); 454 | } 455 | } 456 | // FEATURE : serialize relations and constraints here 457 | 458 | return m; 459 | } 460 | 461 | private string GetXmlSchema(DataTable dt) 462 | { 463 | using (var writer = new StringWriter()) 464 | { 465 | dt.WriteXmlSchema(writer); 466 | return dt.ToString(); 467 | } 468 | } 469 | 470 | private void WriteDataset(DataSet ds) 471 | { 472 | _output.WriteByte(TOKENS.DOC_START); 473 | { 474 | WritePair("$schema", _params.UseOptimizedDatasetSchema ? (object)GetSchema(ds) : ds.GetXmlSchema()); 475 | WriteComma(); 476 | } 477 | bool tablesep = false; 478 | foreach (DataTable table in ds.Tables) 479 | { 480 | if (tablesep) WriteComma(); 481 | tablesep = true; 482 | WriteDataTableData(table); 483 | } 484 | // end dataset 485 | _output.WriteByte(TOKENS.DOC_END); 486 | } 487 | 488 | private void WriteDataTableData(DataTable table) 489 | { 490 | WriteName(table.TableName); 491 | WriteColon(); 492 | _output.WriteByte(TOKENS.ARRAY_START); 493 | DataColumnCollection cols = table.Columns; 494 | bool rowseparator = false; 495 | foreach (DataRow row in table.Rows) 496 | { 497 | if (rowseparator) WriteComma(); 498 | rowseparator = true; 499 | _output.WriteByte(TOKENS.ARRAY_START); 500 | 501 | bool pendingSeperator = false; 502 | foreach (DataColumn column in cols) 503 | { 504 | if (pendingSeperator) WriteComma(); 505 | WriteValue(row[column]); 506 | pendingSeperator = true; 507 | } 508 | _output.WriteByte(TOKENS.ARRAY_END); 509 | } 510 | 511 | _output.WriteByte(TOKENS.ARRAY_END); 512 | } 513 | 514 | void WriteDataTable(DataTable dt) 515 | { 516 | _output.WriteByte(TOKENS.DOC_START); 517 | //if (this.useExtension) 518 | { 519 | this.WritePair("$schema", _params.UseOptimizedDatasetSchema ? (object)this.GetSchema(dt) : this.GetXmlSchema(dt)); 520 | WriteComma(); 521 | } 522 | 523 | WriteDataTableData(dt); 524 | 525 | // end datatable 526 | _output.WriteByte(TOKENS.DOC_END); 527 | } 528 | #endif 529 | bool _TypesWritten = false; 530 | 531 | private void WriteObject(object obj) 532 | { 533 | int i = 0; 534 | if (_cirobj.TryGetValue(obj, out i) == false) 535 | _cirobj.Add(obj, _cirobj.Count + 1); 536 | else 537 | { 538 | if (_current_depth > 0) 539 | { 540 | //_circular = true; 541 | _output.WriteByte(TOKENS.DOC_START); 542 | WriteName("$i"); 543 | WriteColon(); 544 | WriteValue(i); 545 | _output.WriteByte(TOKENS.DOC_END); 546 | return; 547 | } 548 | } 549 | if (_params.UsingGlobalTypes == false) 550 | _output.WriteByte(TOKENS.DOC_START); 551 | else 552 | { 553 | if (_TypesWritten == false) 554 | { 555 | _output.WriteByte(TOKENS.DOC_START); 556 | // write pointer to $types position 557 | _output.WriteByte(TOKENS.TYPES_POINTER); 558 | _typespointer = (int)_output.Length; // place holder 559 | _output.Write(new byte[4], 0, 4); // zero pointer for now 560 | //_output = new MemoryStream(); 561 | _TypesWritten = true; 562 | } 563 | else 564 | _output.WriteByte(TOKENS.DOC_START); 565 | 566 | } 567 | _current_depth++; 568 | if (_current_depth > _MAX_DEPTH) 569 | throw new Exception("Serializer encountered maximum depth of " + _MAX_DEPTH); 570 | 571 | Type t = obj.GetType(); 572 | bool append = false; 573 | if (_params.UseExtensions) 574 | { 575 | if (_params.UsingGlobalTypes == false) 576 | WritePairFast("$type", Reflection.Instance.GetTypeAssemblyName(t)); 577 | else 578 | { 579 | int dt = 0; 580 | string ct = Reflection.Instance.GetTypeAssemblyName(t); 581 | if (_globalTypes.TryGetValue(ct, out dt) == false) 582 | { 583 | dt = _globalTypes.Count + 1; 584 | _globalTypes.Add(ct, dt); 585 | } 586 | WritePairFast("$type", dt.ToString()); 587 | } 588 | append = true; 589 | } 590 | 591 | Getters[] g = Reflection.Instance.GetGetters(t, /*_params.ShowReadOnlyProperties,*/ _params.IgnoreAttributes); 592 | int c = g.Length; 593 | for (int ii = 0; ii < c; ii++) 594 | { 595 | var p = g[ii]; 596 | var o = p.Getter(obj); 597 | if (_params.SerializeNulls == false && (o == null || o is DBNull)) 598 | { 599 | 600 | } 601 | else 602 | { 603 | if (append) 604 | WriteComma(); 605 | WritePair(p.Name, o); 606 | append = true; 607 | } 608 | } 609 | _output.WriteByte(TOKENS.DOC_END); 610 | _current_depth--; 611 | } 612 | 613 | private void WritePairFast(string name, string value) 614 | { 615 | if (_params.SerializeNulls == false && (value == null)) 616 | return; 617 | WriteName(name); 618 | 619 | WriteColon(); 620 | 621 | WriteString(value); 622 | } 623 | 624 | private void WritePair(string name, object value) 625 | { 626 | if (_params.SerializeNulls == false && (value == null || value is DBNull)) 627 | return; 628 | WriteName(name); 629 | 630 | WriteColon(); 631 | 632 | WriteValue(value); 633 | } 634 | 635 | private void WriteArray(IEnumerable array) 636 | { 637 | _output.WriteByte(TOKENS.ARRAY_START); 638 | 639 | bool pendingSeperator = false; 640 | 641 | foreach (object obj in array) 642 | { 643 | if (pendingSeperator) WriteComma(); 644 | 645 | WriteValue(obj); 646 | 647 | pendingSeperator = true; 648 | } 649 | _output.WriteByte(TOKENS.ARRAY_END); 650 | } 651 | 652 | private void WriteStringDictionary(IDictionary dic) 653 | { 654 | _output.WriteByte(TOKENS.DOC_START); 655 | 656 | bool pendingSeparator = false; 657 | 658 | foreach (DictionaryEntry entry in dic) 659 | { 660 | if (pendingSeparator) WriteComma(); 661 | 662 | WritePair((string)entry.Key, entry.Value); 663 | 664 | pendingSeparator = true; 665 | } 666 | _output.WriteByte(TOKENS.DOC_END); 667 | } 668 | 669 | private void WriteStringDictionary(IDictionary dic) 670 | { 671 | _output.WriteByte(TOKENS.DOC_START); 672 | 673 | bool pendingSeparator = false; 674 | 675 | foreach (KeyValuePair entry in dic) 676 | { 677 | if (pendingSeparator) WriteComma(); 678 | 679 | WritePair((string)entry.Key, entry.Value); 680 | 681 | pendingSeparator = true; 682 | } 683 | _output.WriteByte(TOKENS.DOC_END); 684 | } 685 | 686 | private void WriteDictionary(IDictionary dic) 687 | { 688 | _output.WriteByte(TOKENS.ARRAY_START); 689 | 690 | bool pendingSeparator = false; 691 | 692 | foreach (DictionaryEntry entry in dic) 693 | { 694 | if (pendingSeparator) WriteComma(); 695 | _output.WriteByte(TOKENS.DOC_START); 696 | WritePair("k", entry.Key); 697 | WriteComma(); 698 | WritePair("v", entry.Value); 699 | _output.WriteByte(TOKENS.DOC_END); 700 | 701 | pendingSeparator = true; 702 | } 703 | _output.WriteByte(TOKENS.ARRAY_END); 704 | } 705 | 706 | private void WriteName(string s) 707 | { 708 | byte[] b; 709 | if (_params.UseUnicodeStrings == false) 710 | { 711 | _output.WriteByte(TOKENS.NAME); 712 | b = Reflection.UTF8GetBytes(s); 713 | } 714 | else 715 | { 716 | _output.WriteByte(TOKENS.NAME_UNI); 717 | b = Reflection.UnicodeGetBytes(s); 718 | } 719 | _output.WriteByte((byte)b.Length); 720 | _output.Write(b, 0, b.Length % 256); 721 | } 722 | 723 | private void WriteString(string s) 724 | { 725 | byte[] b = null; 726 | if (_params.UseUnicodeStrings) 727 | { 728 | _output.WriteByte(TOKENS.UNICODE_STRING); 729 | b = Reflection.UnicodeGetBytes(s); 730 | } 731 | else 732 | { 733 | _output.WriteByte(TOKENS.STRING); 734 | b = Reflection.UTF8GetBytes(s); 735 | } 736 | _output.Write(Helper.GetBytes(b.Length, false), 0, 4); 737 | _output.Write(b, 0, b.Length); 738 | } 739 | } 740 | } 741 | -------------------------------------------------------------------------------- /fastBinaryJSON/Getters.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace fastBinaryJSON 4 | { 5 | public sealed class DatasetSchema 6 | { 7 | public List Info ;//{ get; set; } 8 | public string Name ;//{ get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /fastBinaryJSON/Reflection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection.Emit; 4 | using System.Reflection; 5 | using System.Collections; 6 | using System.Text; 7 | using System.Runtime.Serialization; 8 | #if NET4 9 | using System.Linq; 10 | #endif 11 | #if !SILVERLIGHT 12 | using System.Data; 13 | #endif 14 | using System.Collections.Specialized; 15 | 16 | namespace fastJSON 17 | { 18 | public struct Getters 19 | { 20 | public string Name; 21 | public string lcName; 22 | public string memberName; 23 | public Reflection.GenericGetter Getter; 24 | public bool ReadOnly; 25 | } 26 | 27 | public enum myPropInfoType 28 | { 29 | Int, 30 | Long, 31 | String, 32 | Bool, 33 | DateTime, 34 | Enum, 35 | Guid, 36 | 37 | Array, 38 | ByteArray, 39 | Dictionary, 40 | StringKeyDictionary, 41 | NameValue, 42 | StringDictionary, 43 | #if !SILVERLIGHT 44 | Hashtable, 45 | DataSet, 46 | DataTable, 47 | #endif 48 | Custom, 49 | Unknown, 50 | } 51 | 52 | public class myPropInfo 53 | { 54 | public Type pt; 55 | public Type bt; 56 | public Type changeType; 57 | public Reflection.GenericSetter setter; 58 | public Reflection.GenericGetter getter; 59 | public Type[] GenericTypes; 60 | public string Name; 61 | #if NET4 62 | public string memberName; 63 | #endif 64 | public myPropInfoType Type; 65 | public bool CanWrite; 66 | 67 | public bool IsClass; 68 | public bool IsValueType; 69 | public bool IsGenericType; 70 | public bool IsStruct; 71 | public bool IsInterface; 72 | } 73 | 74 | public sealed class Reflection 75 | { 76 | // Singleton pattern 4 from : http://csharpindepth.com/articles/general/singleton.aspx 77 | private static readonly Reflection instance = new Reflection(); 78 | // Explicit static constructor to tell C# compiler 79 | // not to mark type as beforefieldinit 80 | static Reflection() 81 | { 82 | } 83 | private Reflection() 84 | { 85 | } 86 | public static Reflection Instance { get { return instance; } } 87 | 88 | public static bool RDBMode = false; 89 | 90 | public delegate string Serialize(object data); 91 | public delegate object Deserialize(string data); 92 | 93 | public delegate object GenericSetter(object target, object value); 94 | public delegate object GenericGetter(object obj); 95 | private delegate object CreateObject(); 96 | private delegate object CreateList(int capacity); 97 | 98 | private SafeDictionary _tyname = new SafeDictionary(10); 99 | private SafeDictionary _typecache = new SafeDictionary(10); 100 | private SafeDictionary _constrcache = new SafeDictionary(10); 101 | private SafeDictionary _conlistcache = new SafeDictionary(10); 102 | private SafeDictionary _getterscache = new SafeDictionary(10); 103 | private SafeDictionary> _propertycache = new SafeDictionary>(10); 104 | private SafeDictionary _genericTypes = new SafeDictionary(10); 105 | private SafeDictionary _genericTypeDef = new SafeDictionary(10); 106 | private static SafeDictionary _opCodes; 107 | private static List _blacklistTypes = new List() 108 | { 109 | "system.configuration.install.assemblyinstaller", 110 | "system.activities.presentation.workflowdesigner", 111 | "system.windows.resourcedictionary", 112 | "system.windows.data.objectdataprovider", 113 | "system.windows.forms.bindingsource", 114 | "microsoft.exchange.management.systemmanager.winforms.exchangesettingsprovider" 115 | }; 116 | 117 | private static bool TryGetOpCode(short code, out OpCode opCode) 118 | { 119 | if (_opCodes != null) 120 | return _opCodes.TryGetValue(code, out opCode); 121 | var dict = new SafeDictionary(); 122 | foreach (var fi in typeof(OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static)) 123 | { 124 | if (!typeof(OpCode).IsAssignableFrom(fi.FieldType)) continue; 125 | var innerOpCode = (OpCode)fi.GetValue(null); 126 | if (innerOpCode.OpCodeType != OpCodeType.Nternal) 127 | dict.Add(innerOpCode.Value, innerOpCode); 128 | } 129 | _opCodes = dict; 130 | return _opCodes.TryGetValue(code, out opCode); 131 | } 132 | 133 | #region bjson custom types 134 | //internal UnicodeEncoding unicode = new UnicodeEncoding(); 135 | private static UTF8Encoding utf8 = new UTF8Encoding(); 136 | 137 | // TODO : optimize utf8 138 | public static byte[] UTF8GetBytes(string str) 139 | { 140 | return utf8.GetBytes(str); 141 | } 142 | 143 | public static string UTF8GetString(byte[] bytes, int offset, int len) 144 | { 145 | return utf8.GetString(bytes, offset, len); 146 | } 147 | 148 | public unsafe static byte[] UnicodeGetBytes(string str) 149 | { 150 | int len = str.Length * 2; 151 | byte[] b = new byte[len]; 152 | fixed (void* ptr = str) 153 | { 154 | System.Runtime.InteropServices.Marshal.Copy(new IntPtr(ptr), b, 0, len); 155 | } 156 | return b; 157 | } 158 | 159 | public static string UnicodeGetString(byte[] b) 160 | { 161 | return UnicodeGetString(b, 0, b.Length); 162 | } 163 | 164 | public unsafe static string UnicodeGetString(byte[] bytes, int offset, int buflen) 165 | { 166 | string str = ""; 167 | fixed (byte* bptr = bytes) 168 | { 169 | char* cptr = (char*)(bptr + offset); 170 | str = new string(cptr, 0, buflen / 2); 171 | } 172 | return str; 173 | } 174 | #endregion 175 | 176 | #region json custom types 177 | // JSON custom 178 | internal SafeDictionary _customSerializer = new SafeDictionary(); 179 | internal SafeDictionary _customDeserializer = new SafeDictionary(); 180 | 181 | internal object CreateCustom(string v, Type type) 182 | { 183 | Deserialize d; 184 | _customDeserializer.TryGetValue(type, out d); 185 | return d(v); 186 | } 187 | 188 | internal void RegisterCustomType(Type type, Serialize serializer, Deserialize deserializer) 189 | { 190 | if (type != null && serializer != null && deserializer != null) 191 | { 192 | _customSerializer.Add(type, serializer); 193 | _customDeserializer.Add(type, deserializer); 194 | // reset property cache 195 | Instance.ResetPropertyCache(); 196 | } 197 | } 198 | 199 | internal bool IsTypeRegistered(Type t) 200 | { 201 | if (_customSerializer.Count() == 0) 202 | return false; 203 | Serialize s; 204 | return _customSerializer.TryGetValue(t, out s); 205 | } 206 | #endregion 207 | 208 | public Type GetGenericTypeDefinition(Type t) 209 | { 210 | Type tt = null; 211 | if (_genericTypeDef.TryGetValue(t, out tt)) 212 | return tt; 213 | else 214 | { 215 | tt = t.GetGenericTypeDefinition(); 216 | _genericTypeDef.Add(t, tt); 217 | return tt; 218 | } 219 | } 220 | 221 | public Type[] GetGenericArguments(Type t) 222 | { 223 | Type[] tt = null; 224 | if (_genericTypes.TryGetValue(t, out tt)) 225 | return tt; 226 | else 227 | { 228 | tt = t.GetGenericArguments(); 229 | _genericTypes.Add(t, tt); 230 | return tt; 231 | } 232 | } 233 | 234 | public Dictionary Getproperties(Type type, string typename, bool ShowReadOnlyProperties) 235 | { 236 | Dictionary sd = null; 237 | if (_propertycache.TryGetValue(typename, out sd)) 238 | { 239 | return sd; 240 | } 241 | else 242 | { 243 | sd = new Dictionary(10); 244 | var bf = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; 245 | PropertyInfo[] pr = type.GetProperties(bf); 246 | foreach (PropertyInfo p in pr) 247 | { 248 | if (p.GetIndexParameters().Length > 0)// Property is an indexer 249 | continue; 250 | 251 | myPropInfo d = CreateMyProp(p.PropertyType, p.Name); 252 | d.setter = Reflection.CreateSetMethod(type, p, ShowReadOnlyProperties); 253 | if (d.setter != null) 254 | d.CanWrite = true; 255 | d.getter = Reflection.CreateGetMethod(type, p); 256 | #if NET4 257 | var att = p.GetCustomAttributes(true); 258 | foreach (var at in att) 259 | { 260 | if (at is DataMemberAttribute) 261 | { 262 | var dm = (DataMemberAttribute)at; 263 | if (dm.Name != "") 264 | d.memberName = dm.Name; 265 | } 266 | } 267 | if (d.memberName != null) 268 | sd.Add(d.memberName, d); 269 | else 270 | #endif 271 | sd.Add(p.Name.ToLowerInvariant(), d); 272 | } 273 | FieldInfo[] fi = type.GetFields(bf); 274 | foreach (FieldInfo f in fi) 275 | { 276 | myPropInfo d = CreateMyProp(f.FieldType, f.Name); 277 | if (f.IsLiteral == false) 278 | { 279 | if (f.IsInitOnly == false) 280 | d.setter = Reflection.CreateSetField(type, f); 281 | if (d.setter != null) 282 | d.CanWrite = true; 283 | d.getter = Reflection.CreateGetField(type, f); 284 | #if NET4 285 | var att = f.GetCustomAttributes(true); 286 | foreach (var at in att) 287 | { 288 | if (at is DataMemberAttribute) 289 | { 290 | var dm = (DataMemberAttribute)at; 291 | if (dm.Name != "") 292 | d.memberName = dm.Name; 293 | } 294 | } 295 | if (d.memberName != null) 296 | sd.Add(d.memberName, d); 297 | else 298 | #endif 299 | sd.Add(f.Name.ToLowerInvariant(), d); 300 | } 301 | } 302 | 303 | _propertycache.Add(typename, sd); 304 | return sd; 305 | } 306 | } 307 | 308 | private myPropInfo CreateMyProp(Type t, string name) 309 | { 310 | myPropInfo d = new myPropInfo(); 311 | myPropInfoType d_type = myPropInfoType.Unknown; 312 | 313 | if (t == typeof(int) || t == typeof(int?)) d_type = myPropInfoType.Int; 314 | else if (t == typeof(long) || t == typeof(long?)) d_type = myPropInfoType.Long; 315 | else if (t == typeof(string)) d_type = myPropInfoType.String; 316 | else if (t == typeof(bool) || t == typeof(bool?)) d_type = myPropInfoType.Bool; 317 | else if (t == typeof(DateTime) || t == typeof(DateTime?)) d_type = myPropInfoType.DateTime; 318 | else if (t.IsEnum) d_type = myPropInfoType.Enum; 319 | else if (t == typeof(Guid) || t == typeof(Guid?)) d_type = myPropInfoType.Guid; 320 | else if (t == typeof(StringDictionary)) d_type = myPropInfoType.StringDictionary; 321 | else if (t == typeof(NameValueCollection)) d_type = myPropInfoType.NameValue; 322 | else if (t.IsArray) 323 | { 324 | d.bt = t.GetElementType(); 325 | if (t == typeof(byte[])) 326 | d_type = myPropInfoType.ByteArray; 327 | else 328 | d_type = myPropInfoType.Array; 329 | } 330 | else if (t.Name.Contains("Dictionary")) 331 | { 332 | d.GenericTypes = Reflection.Instance.GetGenericArguments(t); 333 | if (d.GenericTypes.Length > 0 && d.GenericTypes[0] == typeof(string)) 334 | d_type = myPropInfoType.StringKeyDictionary; 335 | else 336 | d_type = myPropInfoType.Dictionary; 337 | } 338 | #if !SILVERLIGHT 339 | else if (t == typeof(Hashtable)) d_type = myPropInfoType.Hashtable; 340 | else if (t == typeof(DataSet)) d_type = myPropInfoType.DataSet; 341 | else if (t == typeof(DataTable)) d_type = myPropInfoType.DataTable; 342 | #endif 343 | else if (IsTypeRegistered(t)) 344 | d_type = myPropInfoType.Custom; 345 | 346 | if (t.IsValueType && !t.IsPrimitive && !t.IsEnum && t != typeof(decimal)) 347 | d.IsStruct = true; 348 | 349 | d.IsInterface = t.IsInterface; 350 | d.IsClass = t.IsClass; 351 | d.IsValueType = t.IsValueType; 352 | if (t.IsGenericType) 353 | { 354 | d.IsGenericType = true; 355 | d.bt = Reflection.Instance.GetGenericArguments(t)[0]; 356 | } 357 | 358 | d.pt = t; 359 | d.Name = name; 360 | d.changeType = GetChangeType(t); 361 | d.Type = d_type; 362 | 363 | return d; 364 | } 365 | 366 | private Type GetChangeType(Type conversionType) 367 | { 368 | if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) 369 | return Reflection.Instance.GetGenericArguments(conversionType)[0]; 370 | 371 | return conversionType; 372 | } 373 | 374 | #region [ PROPERTY GET SET ] 375 | 376 | public string GetTypeAssemblyName(Type t) 377 | { 378 | string val = ""; 379 | if (_tyname.TryGetValue(t, out val)) 380 | return val; 381 | else 382 | { 383 | string s = t.AssemblyQualifiedName; 384 | _tyname.Add(t, s); 385 | return s; 386 | } 387 | } 388 | 389 | internal Type GetTypeFromCache(string typename, bool blacklistChecking) 390 | { 391 | Type val = null; 392 | if (_typecache.TryGetValue(typename, out val)) 393 | return val; 394 | else 395 | { 396 | // check for BLACK LIST types -> more secure when using $type 397 | if (blacklistChecking) 398 | { 399 | var tn = typename.Trim().ToLowerInvariant(); 400 | foreach (var s in _blacklistTypes) 401 | if (tn.StartsWith(s, StringComparison.Ordinal)) 402 | throw new Exception("Black list type encountered, possible attack vector when using $type : " + typename); 403 | } 404 | 405 | Type t = Type.GetType(typename); 406 | #if NET4 407 | if (RDBMode) 408 | { 409 | if (t == null) // RaptorDB : loading runtime assemblies 410 | { 411 | t = Type.GetType(typename, (name) => 412 | { 413 | return AppDomain.CurrentDomain.GetAssemblies().Where(z => z.FullName == name.FullName).FirstOrDefault(); 414 | }, null, true); 415 | } 416 | } 417 | #endif 418 | _typecache.Add(typename, t); 419 | return t; 420 | } 421 | } 422 | 423 | internal object FastCreateList(Type objtype, int capacity) 424 | { 425 | try 426 | { 427 | int count = 10; 428 | if (capacity > 10) 429 | count = capacity; 430 | CreateList c = null; 431 | if (_conlistcache.TryGetValue(objtype, out c)) 432 | { 433 | if (c != null) // kludge : non capacity lists 434 | return c(count); 435 | else 436 | return FastCreateInstance(objtype); 437 | } 438 | else 439 | { 440 | var cinfo = objtype.GetConstructor(new Type[] { typeof(int) }); 441 | if (cinfo != null) 442 | { 443 | DynamicMethod dynMethod = new DynamicMethod("_fcil", objtype, new Type[] { typeof(int) }, true); 444 | ILGenerator ilGen = dynMethod.GetILGenerator(); 445 | ilGen.Emit(OpCodes.Ldarg_0); 446 | ilGen.Emit(OpCodes.Newobj, objtype.GetConstructor(new Type[] { typeof(int) })); 447 | ilGen.Emit(OpCodes.Ret); 448 | c = (CreateList)dynMethod.CreateDelegate(typeof(CreateList)); 449 | _conlistcache.Add(objtype, c); 450 | return c(count); 451 | } 452 | else 453 | { 454 | _conlistcache.Add(objtype, null);// kludge : non capacity lists 455 | return FastCreateInstance(objtype); 456 | } 457 | } 458 | } 459 | catch (Exception exc) 460 | { 461 | throw new Exception(string.Format("Failed to fast create instance for type '{0}' from assembly '{1}'", 462 | objtype.FullName, objtype.AssemblyQualifiedName), exc); 463 | } 464 | } 465 | 466 | internal object FastCreateInstance(Type objtype) 467 | { 468 | try 469 | { 470 | CreateObject c = null; 471 | if (_constrcache.TryGetValue(objtype, out c)) 472 | { 473 | return c(); 474 | } 475 | else 476 | { 477 | if (objtype.IsClass) 478 | { 479 | DynamicMethod dynMethod = new DynamicMethod("_fcic", objtype, null, true); 480 | ILGenerator ilGen = dynMethod.GetILGenerator(); 481 | ilGen.Emit(OpCodes.Newobj, objtype.GetConstructor(Type.EmptyTypes)); 482 | ilGen.Emit(OpCodes.Ret); 483 | c = (CreateObject)dynMethod.CreateDelegate(typeof(CreateObject)); 484 | _constrcache.Add(objtype, c); 485 | } 486 | else // structs 487 | { 488 | DynamicMethod dynMethod = new DynamicMethod("_fcis", typeof(object), null, true); 489 | ILGenerator ilGen = dynMethod.GetILGenerator(); 490 | var lv = ilGen.DeclareLocal(objtype); 491 | ilGen.Emit(OpCodes.Ldloca_S, lv); 492 | ilGen.Emit(OpCodes.Initobj, objtype); 493 | ilGen.Emit(OpCodes.Ldloc_0); 494 | ilGen.Emit(OpCodes.Box, objtype); 495 | ilGen.Emit(OpCodes.Ret); 496 | c = (CreateObject)dynMethod.CreateDelegate(typeof(CreateObject)); 497 | _constrcache.Add(objtype, c); 498 | } 499 | return c(); 500 | } 501 | } 502 | catch (Exception exc) 503 | { 504 | throw new Exception(string.Format("Failed to fast create instance for type '{0}' from assembly '{1}'", 505 | objtype.FullName, objtype.AssemblyQualifiedName), exc); 506 | } 507 | } 508 | 509 | internal static GenericSetter CreateSetField(Type type, FieldInfo fieldInfo) 510 | { 511 | Type[] arguments = new Type[2]; 512 | arguments[0] = arguments[1] = typeof(object); 513 | 514 | DynamicMethod dynamicSet = new DynamicMethod("_csf", typeof(object), arguments, type, true); 515 | 516 | ILGenerator il = dynamicSet.GetILGenerator(); 517 | 518 | if (!type.IsClass) // structs 519 | { 520 | var lv = il.DeclareLocal(type); 521 | il.Emit(OpCodes.Ldarg_0); 522 | il.Emit(OpCodes.Unbox_Any, type); 523 | il.Emit(OpCodes.Stloc_0); 524 | il.Emit(OpCodes.Ldloca_S, lv); 525 | il.Emit(OpCodes.Ldarg_1); 526 | if (fieldInfo.FieldType.IsClass) 527 | il.Emit(OpCodes.Castclass, fieldInfo.FieldType); 528 | else 529 | il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType); 530 | il.Emit(OpCodes.Stfld, fieldInfo); 531 | il.Emit(OpCodes.Ldloc_0); 532 | il.Emit(OpCodes.Box, type); 533 | il.Emit(OpCodes.Ret); 534 | } 535 | else 536 | { 537 | il.Emit(OpCodes.Ldarg_0); 538 | il.Emit(OpCodes.Ldarg_1); 539 | if (fieldInfo.FieldType.IsValueType) 540 | il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType); 541 | il.Emit(OpCodes.Stfld, fieldInfo); 542 | il.Emit(OpCodes.Ldarg_0); 543 | il.Emit(OpCodes.Ret); 544 | } 545 | return (GenericSetter)dynamicSet.CreateDelegate(typeof(GenericSetter)); 546 | } 547 | 548 | internal static FieldInfo GetGetterBackingField(PropertyInfo autoProperty) 549 | { 550 | var getMethod = autoProperty.GetGetMethod(); 551 | // Restrict operation to auto properties to avoid risking errors if a getter does not contain exactly one field read instruction (such as with calculated properties). 552 | if (!getMethod.IsDefined(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), false)) return null; 553 | 554 | var byteCode = getMethod.GetMethodBody()?.GetILAsByteArray() ?? new byte[0]; 555 | //var byteCode = getMethod.GetMethodBody().GetILAsByteArray(); 556 | int pos = 0; 557 | // Find the first LdFld instruction and parse its operand to a FieldInfo object. 558 | while (pos < byteCode.Length) 559 | { 560 | // Read and parse the OpCode (it can be 1 or 2 bytes in size). 561 | byte code = byteCode[pos++]; 562 | if (!(TryGetOpCode(code, out var opCode) || pos < byteCode.Length && TryGetOpCode((short)(code * 0x100 + byteCode[pos++]), out opCode))) 563 | throw new NotSupportedException("Unknown IL code detected."); 564 | // If it is a LdFld, read its operand, parse it to a FieldInfo and return it. 565 | if (opCode == OpCodes.Ldfld && opCode.OperandType == OperandType.InlineField && pos + sizeof(int) <= byteCode.Length) 566 | { 567 | return getMethod.Module.ResolveMember(BitConverter.ToInt32(byteCode, pos), getMethod.DeclaringType?.GetGenericArguments(), null) as FieldInfo; 568 | } 569 | // Otherwise, set the current position to the start of the next instruction, if any (we need to know how much bytes are used by operands). 570 | pos += opCode.OperandType == OperandType.InlineNone 571 | ? 0 572 | : opCode.OperandType == OperandType.ShortInlineBrTarget || 573 | opCode.OperandType == OperandType.ShortInlineI || 574 | opCode.OperandType == OperandType.ShortInlineVar 575 | ? 1 576 | : opCode.OperandType == OperandType.InlineVar 577 | ? 2 578 | : opCode.OperandType == OperandType.InlineI8 || 579 | opCode.OperandType == OperandType.InlineR 580 | ? 8 581 | : opCode.OperandType == OperandType.InlineSwitch 582 | ? 4 * (BitConverter.ToInt32(byteCode, pos) + 1) 583 | : 4; 584 | } 585 | return null; 586 | } 587 | 588 | internal static GenericSetter CreateSetMethod(Type type, PropertyInfo propertyInfo, bool ShowReadOnlyProperties) 589 | { 590 | MethodInfo setMethod = propertyInfo.GetSetMethod(ShowReadOnlyProperties); 591 | if (setMethod == null) 592 | { 593 | if (!ShowReadOnlyProperties) return null; 594 | // If the property has no setter and it is an auto property, try and create a setter for its backing field instead 595 | var fld = GetGetterBackingField(propertyInfo); 596 | return fld != null ? CreateSetField(type, fld) : null; 597 | } 598 | 599 | Type[] arguments = new Type[2]; 600 | arguments[0] = arguments[1] = typeof(object); 601 | 602 | DynamicMethod setter = new DynamicMethod("_csm", typeof(object), arguments, true);// !setMethod.IsPublic); // fix: skipverify 603 | ILGenerator il = setter.GetILGenerator(); 604 | 605 | if (!type.IsClass) // structs 606 | { 607 | var lv = il.DeclareLocal(type); 608 | il.Emit(OpCodes.Ldarg_0); 609 | il.Emit(OpCodes.Unbox_Any, type); 610 | il.Emit(OpCodes.Stloc_0); 611 | il.Emit(OpCodes.Ldloca_S, lv); 612 | il.Emit(OpCodes.Ldarg_1); 613 | if (propertyInfo.PropertyType.IsClass) 614 | il.Emit(OpCodes.Castclass, propertyInfo.PropertyType); 615 | else 616 | il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); 617 | il.EmitCall(OpCodes.Call, setMethod, null); 618 | il.Emit(OpCodes.Ldloc_0); 619 | il.Emit(OpCodes.Box, type); 620 | } 621 | else 622 | { 623 | if (!setMethod.IsStatic) 624 | { 625 | il.Emit(OpCodes.Ldarg_0); 626 | il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType); 627 | il.Emit(OpCodes.Ldarg_1); 628 | if (propertyInfo.PropertyType.IsClass) 629 | il.Emit(OpCodes.Castclass, propertyInfo.PropertyType); 630 | else 631 | il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); 632 | il.EmitCall(OpCodes.Callvirt, setMethod, null); 633 | il.Emit(OpCodes.Ldarg_0); 634 | } 635 | else 636 | { 637 | il.Emit(OpCodes.Ldarg_0); 638 | il.Emit(OpCodes.Ldarg_1); 639 | if (propertyInfo.PropertyType.IsClass) 640 | il.Emit(OpCodes.Castclass, propertyInfo.PropertyType); 641 | else 642 | il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); 643 | il.Emit(OpCodes.Call, setMethod); 644 | } 645 | } 646 | 647 | il.Emit(OpCodes.Ret); 648 | 649 | return (GenericSetter)setter.CreateDelegate(typeof(GenericSetter)); 650 | } 651 | 652 | internal static GenericGetter CreateGetField(Type type, FieldInfo fieldInfo) 653 | { 654 | DynamicMethod dynamicGet = new DynamicMethod("_cgf", typeof(object), new Type[] { typeof(object) }, type, true); 655 | 656 | ILGenerator il = dynamicGet.GetILGenerator(); 657 | 658 | if (!type.IsClass) // structs 659 | { 660 | var lv = il.DeclareLocal(type); 661 | il.Emit(OpCodes.Ldarg_0); 662 | il.Emit(OpCodes.Unbox_Any, type); 663 | il.Emit(OpCodes.Stloc_0); 664 | il.Emit(OpCodes.Ldloca_S, lv); 665 | il.Emit(OpCodes.Ldfld, fieldInfo); 666 | if (fieldInfo.FieldType.IsValueType) 667 | il.Emit(OpCodes.Box, fieldInfo.FieldType); 668 | } 669 | else 670 | { 671 | il.Emit(OpCodes.Ldarg_0); 672 | il.Emit(OpCodes.Ldfld, fieldInfo); 673 | if (fieldInfo.FieldType.IsValueType) 674 | il.Emit(OpCodes.Box, fieldInfo.FieldType); 675 | } 676 | 677 | il.Emit(OpCodes.Ret); 678 | 679 | return (GenericGetter)dynamicGet.CreateDelegate(typeof(GenericGetter)); 680 | } 681 | 682 | internal static GenericGetter CreateGetMethod(Type type, PropertyInfo propertyInfo) 683 | { 684 | MethodInfo getMethod = propertyInfo.GetGetMethod(); 685 | if (getMethod == null) 686 | return null; 687 | 688 | DynamicMethod getter = new DynamicMethod("_cgm", typeof(object), new Type[] { typeof(object) }, type, true); 689 | 690 | ILGenerator il = getter.GetILGenerator(); 691 | 692 | if (!type.IsClass) // structs 693 | { 694 | var lv = il.DeclareLocal(type); 695 | il.Emit(OpCodes.Ldarg_0); 696 | il.Emit(OpCodes.Unbox_Any, type); 697 | il.Emit(OpCodes.Stloc_0); 698 | il.Emit(OpCodes.Ldloca_S, lv); 699 | il.EmitCall(OpCodes.Call, getMethod, null); 700 | if (propertyInfo.PropertyType.IsValueType) 701 | il.Emit(OpCodes.Box, propertyInfo.PropertyType); 702 | } 703 | else 704 | { 705 | if (!getMethod.IsStatic) 706 | { 707 | il.Emit(OpCodes.Ldarg_0); 708 | il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType); 709 | il.EmitCall(OpCodes.Callvirt, getMethod, null); 710 | } 711 | else 712 | il.Emit(OpCodes.Call, getMethod); 713 | 714 | if (propertyInfo.PropertyType.IsValueType) 715 | il.Emit(OpCodes.Box, propertyInfo.PropertyType); 716 | } 717 | 718 | il.Emit(OpCodes.Ret); 719 | 720 | return (GenericGetter)getter.CreateDelegate(typeof(GenericGetter)); 721 | } 722 | 723 | public Getters[] GetGetters(Type type, /*bool ShowReadOnlyProperties,*/ List IgnoreAttributes) 724 | { 725 | Getters[] val = null; 726 | if (_getterscache.TryGetValue(type, out val)) 727 | return val; 728 | 729 | var bf = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; 730 | //if (ShowReadOnlyProperties) 731 | // bf |= BindingFlags.NonPublic; 732 | PropertyInfo[] props = type.GetProperties(bf); 733 | List getters = new List(); 734 | foreach (PropertyInfo p in props) 735 | { 736 | bool read_only = false; 737 | if (p.GetIndexParameters().Length > 0) 738 | {// Property is an indexer 739 | continue; 740 | } 741 | if (!p.CanWrite)// && (ShowReadOnlyProperties == false))//|| isAnonymous == false)) 742 | read_only = true; //continue; 743 | if (IgnoreAttributes != null) 744 | { 745 | bool found = false; 746 | foreach (var ignoreAttr in IgnoreAttributes) 747 | { 748 | if (p.IsDefined(ignoreAttr, false)) 749 | { 750 | found = true; 751 | break; 752 | } 753 | } 754 | if (found) 755 | continue; 756 | } 757 | string mName = null; 758 | #if NET4 759 | var att = p.GetCustomAttributes(true); 760 | foreach (var at in att) 761 | { 762 | if (at is DataMemberAttribute) 763 | { 764 | var dm = (DataMemberAttribute)at; 765 | if (dm.Name != "") 766 | { 767 | mName = dm.Name; 768 | } 769 | } 770 | } 771 | #endif 772 | GenericGetter g = CreateGetMethod(type, p); 773 | if (g != null) 774 | getters.Add(new Getters { Getter = g, Name = p.Name, lcName = p.Name.ToLowerInvariant(), memberName = mName, ReadOnly = read_only }); 775 | } 776 | 777 | FieldInfo[] fi = type.GetFields(bf); 778 | foreach (var f in fi) 779 | { 780 | bool read_only = false; 781 | if (f.IsInitOnly) // && (ShowReadOnlyProperties == false))//|| isAnonymous == false)) 782 | read_only = true;//continue; 783 | if (IgnoreAttributes != null) 784 | { 785 | bool found = false; 786 | foreach (var ignoreAttr in IgnoreAttributes) 787 | { 788 | if (f.IsDefined(ignoreAttr, false)) 789 | { 790 | found = true; 791 | break; 792 | } 793 | } 794 | if (found) 795 | continue; 796 | } 797 | string mName = null; 798 | #if NET4 799 | var att = f.GetCustomAttributes(true); 800 | foreach (var at in att) 801 | { 802 | if (at is DataMemberAttribute) 803 | { 804 | var dm = (DataMemberAttribute)at; 805 | if (dm.Name != "") 806 | { 807 | mName = dm.Name; 808 | } 809 | } 810 | } 811 | #endif 812 | if (f.IsLiteral == false) 813 | { 814 | GenericGetter g = CreateGetField(type, f); 815 | if (g != null) 816 | getters.Add(new Getters { Getter = g, Name = f.Name, lcName = f.Name.ToLowerInvariant(), memberName = mName, ReadOnly = read_only }); 817 | } 818 | } 819 | val = getters.ToArray(); 820 | _getterscache.Add(type, val); 821 | return val; 822 | } 823 | 824 | //private static bool IsAnonymousType(Type type) 825 | //{ 826 | // // may break in the future if compiler defined names change... 827 | // const string CS_ANONYMOUS_PREFIX = "<>f__AnonymousType"; 828 | // const string VB_ANONYMOUS_PREFIX = "VB$AnonymousType"; 829 | 830 | // if (type == null) 831 | // throw new ArgumentNullException("type"); 832 | 833 | // if (type.Name.StartsWith(CS_ANONYMOUS_PREFIX, StringComparison.Ordinal) || type.Name.StartsWith(VB_ANONYMOUS_PREFIX, StringComparison.Ordinal)) 834 | // { 835 | // return type.IsDefined(typeof(CompilerGeneratedAttribute), false); 836 | // } 837 | 838 | // return false; 839 | //} 840 | #endregion 841 | 842 | internal void ResetPropertyCache() 843 | { 844 | _propertycache = new SafeDictionary>(); 845 | } 846 | 847 | internal void ClearReflectionCache() 848 | { 849 | _tyname = new SafeDictionary(10); 850 | _typecache = new SafeDictionary(10); 851 | _constrcache = new SafeDictionary(10); 852 | _getterscache = new SafeDictionary(10); 853 | _propertycache = new SafeDictionary>(10); 854 | _genericTypes = new SafeDictionary(10); 855 | _genericTypeDef = new SafeDictionary(10); 856 | } 857 | } 858 | } 859 | -------------------------------------------------------------------------------- /fastBinaryJSON/SafeDictionary.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace fastJSON 5 | { 6 | internal sealed class SafeDictionary 7 | { 8 | private readonly object _Padlock = new object(); 9 | private readonly Dictionary _Dictionary; 10 | 11 | public SafeDictionary(int capacity) 12 | { 13 | _Dictionary = new Dictionary(capacity); 14 | } 15 | 16 | public SafeDictionary() 17 | { 18 | _Dictionary = new Dictionary(); 19 | } 20 | 21 | public bool TryGetValue(TKey key, out TValue value) 22 | { 23 | lock (_Padlock) 24 | return _Dictionary.TryGetValue(key, out value); 25 | } 26 | 27 | public int Count() 28 | { 29 | lock (_Padlock) return _Dictionary.Count; 30 | } 31 | 32 | public TValue this[TKey key] 33 | { 34 | get 35 | { 36 | lock (_Padlock) 37 | return _Dictionary[key]; 38 | } 39 | set 40 | { 41 | lock (_Padlock) 42 | _Dictionary[key] = value; 43 | } 44 | } 45 | 46 | public void Add(TKey key, TValue value) 47 | { 48 | lock (_Padlock) 49 | { 50 | if (_Dictionary.ContainsKey(key) == false) 51 | _Dictionary.Add(key, value); 52 | } 53 | } 54 | } 55 | 56 | internal static class Helper 57 | { 58 | internal static unsafe int ToInt32(byte[] value, int startIndex, bool reverse) 59 | { 60 | if (reverse) 61 | { 62 | byte[] b = new byte[4]; 63 | Buffer.BlockCopy(value, startIndex, b, 0, 4); 64 | Array.Reverse(b); 65 | return ToInt32(b, 0); 66 | } 67 | 68 | return ToInt32(value, startIndex); 69 | } 70 | 71 | internal static unsafe int ToInt32(byte[] value, int startIndex) 72 | { 73 | fixed (byte* numRef = &(value[startIndex])) 74 | { 75 | return *((int*)numRef); 76 | } 77 | } 78 | 79 | internal static unsafe long ToInt64(byte[] value, int startIndex, bool reverse) 80 | { 81 | if (reverse) 82 | { 83 | byte[] b = new byte[8]; 84 | Buffer.BlockCopy(value, startIndex, b, 0, 8); 85 | Array.Reverse(b); 86 | return ToInt64(b, 0); 87 | } 88 | return ToInt64(value, startIndex); 89 | } 90 | 91 | internal static unsafe long ToInt64(byte[] value, int startIndex) 92 | { 93 | fixed (byte* numRef = &(value[startIndex])) 94 | { 95 | return *(((long*)numRef)); 96 | } 97 | } 98 | 99 | internal static unsafe short ToInt16(byte[] value, int startIndex, bool reverse) 100 | { 101 | if (reverse) 102 | { 103 | byte[] b = new byte[2]; 104 | Buffer.BlockCopy(value, startIndex, b, 0, 2); 105 | Array.Reverse(b); 106 | return ToInt16(b, 0); 107 | } 108 | return ToInt16(value, startIndex); 109 | } 110 | 111 | internal static unsafe short ToInt16(byte[] value, int startIndex) 112 | { 113 | fixed (byte* numRef = &(value[startIndex])) 114 | { 115 | return *(((short*)numRef)); 116 | } 117 | } 118 | 119 | internal static unsafe byte[] GetBytes(long num, bool reverse) 120 | { 121 | byte[] buffer = new byte[8]; 122 | fixed (byte* numRef = buffer) 123 | { 124 | *((long*)numRef) = num; 125 | } 126 | if (reverse) 127 | Array.Reverse(buffer); 128 | return buffer; 129 | } 130 | 131 | public static unsafe byte[] GetBytes(int num, bool reverse) 132 | { 133 | byte[] buffer = new byte[4]; 134 | fixed (byte* numRef = buffer) 135 | { 136 | *((int*)numRef) = num; 137 | } 138 | if (reverse) 139 | Array.Reverse(buffer); 140 | return buffer; 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /fastBinaryJSON/dynamic.cs: -------------------------------------------------------------------------------- 1 | #if NET4 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Dynamic; 6 | 7 | namespace fastBinaryJSON 8 | { 9 | internal class DynamicJson : DynamicObject, IEnumerable 10 | { 11 | private IDictionary _dictionary { get; set; } 12 | private List _list { get; set; } 13 | 14 | public DynamicJson(byte[] json) 15 | { 16 | var parse = fastBinaryJSON.BJSON.Parse(json); 17 | 18 | if (parse is IDictionary) 19 | _dictionary = (IDictionary)parse; 20 | else if (parse is typedarray) 21 | _list = ((typedarray)parse).data; 22 | else 23 | _list = (List)parse; 24 | } 25 | 26 | private DynamicJson(object dictionary) 27 | { 28 | if (dictionary is IDictionary) 29 | _dictionary = (IDictionary)dictionary; 30 | } 31 | 32 | public override bool TryGetIndex(GetIndexBinder binder, Object[] indexes, out Object result) 33 | { 34 | var index = indexes[0]; 35 | if (index is int) 36 | { 37 | result = _list[(int)index]; 38 | } 39 | else 40 | { 41 | result = _dictionary[(string)index]; 42 | } 43 | if (result is IDictionary) 44 | result = new DynamicJson(result as IDictionary); 45 | return true; 46 | } 47 | 48 | public override bool TryGetMember(GetMemberBinder binder, out object result) 49 | { 50 | if (_dictionary.TryGetValue(binder.Name, out result) == false) 51 | if (_dictionary.TryGetValue(binder.Name.ToLowerInvariant(), out result) == false) 52 | return false;// throw new Exception("property not found " + binder.Name); 53 | 54 | if (result is IDictionary) 55 | { 56 | result = new DynamicJson(result as IDictionary); 57 | } 58 | else if (result is List) 59 | { 60 | List list = new List(); 61 | foreach (object item in (List)result) 62 | { 63 | if (item is IDictionary) 64 | list.Add(new DynamicJson(item as IDictionary)); 65 | else 66 | list.Add(item); 67 | } 68 | result = list; 69 | } 70 | 71 | return _dictionary.ContainsKey(binder.Name); 72 | } 73 | 74 | public IEnumerator GetEnumerator() 75 | { 76 | foreach (var o in _list) 77 | { 78 | yield return new DynamicJson(o as IDictionary); 79 | } 80 | } 81 | } 82 | } 83 | #endif -------------------------------------------------------------------------------- /fastBinaryJSON/fastBinaryJSON-android.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 10.0.0 7 | 2.0 8 | {9688DEFA-FE57-474D-84B8-30353D957EAC} 9 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10 | Library 11 | fastBinaryJSONandroid 12 | Resources 13 | Assets 14 | fastBinaryJSON-android 15 | 16 | 17 | True 18 | full 19 | False 20 | bin\Debug 21 | DEBUG; SILVERLIGHT 22 | prompt 23 | 4 24 | False 25 | None 26 | 27 | 28 | none 29 | True 30 | bin\Release 31 | prompt 32 | 4 33 | False 34 | SdkOnly 35 | False 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /fastBinaryJSON/fastBinaryJSON.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {207E91B1-C9F8-4913-88E1-3549EF5F3273} 9 | Library 10 | Properties 11 | fastBinaryJSON 12 | fastBinaryJSON 13 | v4.0 14 | 512 15 | True 16 | False 17 | false 18 | true 19 | False 20 | OnBuildSuccess 21 | 22 | 23 | 24 | 25 | 3.5 26 | 27 | 28 | publish\ 29 | true 30 | Disk 31 | false 32 | Foreground 33 | 7 34 | Days 35 | false 36 | false 37 | true 38 | 0 39 | 1.0.0.%2a 40 | false 41 | false 42 | true 43 | 44 | 45 | true 46 | Full 47 | true 48 | ..\output\net40\ 49 | prompt 50 | 4 51 | DEBUG;NET4 52 | false 53 | 54 | 55 | full 56 | true 57 | bin\Release\ 58 | prompt 59 | 4 60 | true 61 | false 62 | 63 | 64 | False 65 | Project 66 | 67 | 68 | False 69 | Off 70 | 4194304 71 | AnyCPU 72 | 73 | 74 | TRACE;NET4 75 | 76 | 77 | fastJSON.snk 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | False 98 | Microsoft .NET Framework 4 %28x86 and x64%29 99 | true 100 | 101 | 102 | False 103 | .NET Framework 3.5 SP1 Client Profile 104 | false 105 | 106 | 107 | False 108 | .NET Framework 3.5 SP1 109 | false 110 | 111 | 112 | False 113 | Windows Installer 3.1 114 | true 115 | 116 | 117 | 118 | 119 | 120 | 121 | 128 | -------------------------------------------------------------------------------- /fastBinaryJSON/fastJSON.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/fastBinaryJSON/8f6bf092bb8f3e60276dc7df11be787f71a63eb8/fastBinaryJSON/fastJSON.snk -------------------------------------------------------------------------------- /fastBinaryJSONcore.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2010 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "fastBinaryJSON", "fastBinaryJSONcore\fastBinaryJSON.csproj", "{F257F0C2-B7D4-46C4-80E4-2A028988910B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {F257F0C2-B7D4-46C4-80E4-2A028988910B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {F257F0C2-B7D4-46C4-80E4-2A028988910B}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {F257F0C2-B7D4-46C4-80E4-2A028988910B}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {F257F0C2-B7D4-46C4-80E4-2A028988910B}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {9D0E41ED-48C3-4773-A3E2-608A4940468B} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /fastBinaryJSONcore/fastBinaryJSON.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0;net4.0 5 | false 6 | 1.5.0.0 7 | 1.5.0.0 8 | smallest fastest polymorphic binary json serializer 9 | 2010-2018 10 | M. Gholam 11 | https://www.codeproject.com/Articles/159450/fastJSON 12 | true 13 | fastBinaryJSON.snk 14 | 15 | 16 | 17 | TRACE;DEBUG;NETSTANDARD2_0 ;net4 ; NETSTANDARD2_0; NET4 18 | ..\output\ 19 | true 20 | true 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 4.3.0 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /fastBinaryJSONcore/fastBinaryJSON.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/fastBinaryJSON/8f6bf092bb8f3e60276dc7df11be787f71a63eb8/fastBinaryJSONcore/fastBinaryJSON.snk -------------------------------------------------------------------------------- /history.txt: -------------------------------------------------------------------------------- 1 | v1.6.1 2 | ------ 3 | - optimized black list checking 4 | 5 | v1.6.0 6 | ------ 7 | - friday 13th json attack checking 8 | 9 | v1.5.3 10 | ------ 11 | - synced Reflection.cs with fastJSON v2.2.5 12 | 13 | v1.5.2 14 | ------ 15 | - bug fix datasets with sbyte data 16 | 17 | v1.5.1 18 | ------ 19 | - fixed fast creating lists without capacity constructor 20 | - fixed signing in .net35 project 21 | - unified Reflection.cs 22 | - backward compatible v1.4 typed arrays data bytes with BJSONParameters.v1_4TypedArray 23 | - * breaking runtime change if using RegisterCustomType() * 24 | 25 | v1.5.0 26 | ------ 27 | - moved .net 3.5 project to own folder to mitigate conflicting obj builds 28 | - carried over fastjson style optimizations 29 | - major string optimizations ~46% faster if using unicode strings 30 | - * breaking changes in output bytes (when using typed arrays) * 31 | 32 | v1.4.24 33 | ------- 34 | - fixed Typed Arrays of value types are serialized incorrectly when they are the root object (thanks to rbeurskens) 35 | - ability to create internal/private objects (removed the public access restriction on classes) 36 | 37 | v1.4.23 38 | ------- 39 | - fixed side effect of changing BJSONParameters.UsingGlobalTypes inside classes and affecting the original value 40 | - fixed deserialize nested Dictionary without extensions with generic ToObject<> 41 | - fixed root enum deserialize (thanks to al6uiz) 42 | - Non public setter / readonly property support (thanks to rbeurskens) 43 | - unify reflection.cs with fastJSON 44 | 45 | v1.4.22 46 | ------- 47 | - bug fix edge case in typed array with long >255 byte type names 48 | 49 | v1.4.21 50 | ------- 51 | - bug fix deserializing array of objects with type information 52 | - test for above 53 | - support for .net core and netstandard2.0 via separate project 54 | 55 | v1.4.20 56 | ------- 57 | - added TimeSpan 58 | - added digit limit tests 59 | 60 | v1.4.19 61 | ------- 62 | - added TOKENS.ARRAY_TYPED for typed arrays 63 | - deserialize t[] into an object correctly as t[] not object[] 64 | - added BJSONParameters.UseTypedArrays to control above (default = true) 65 | - renamed main solution file 66 | - added TOKENS.TYPES_POINTER for $types into bytes stream at the end 67 | - optimize serialize memory usage 68 | - if you put a DataSet into an object then it will deserialize correctly 69 | 70 | v1.4.18 71 | ------- 72 | - bug fix enumerating dynamic objects 73 | 74 | v1.4.17 75 | ------- 76 | - bug fix nested dictionary D<,D<,>> 77 | 78 | v1.4.16 79 | ------- 80 | - added support for interface object properties (thanks to DrDeadCrash) 81 | 82 | v1.4.15 83 | ------- 84 | - synced reflection.cs with fastJSON 85 | - bug fix read only properties to output 86 | - added test for readonly properties 87 | - added NonSerialized to the list of ignore default attributes 88 | - support for ExpandoObject serialization with test 89 | 90 | v1.4.14 91 | ------- 92 | - bug fix DateTime in anonymous type InvalidProgramException (thanks to skottmckay) 93 | - fixed broken custom type handler (sorry to all) 94 | - added test for custom types 95 | - fixed byte[] in Dictionary values with test 96 | 97 | v1.4.13 98 | ------- 99 | - bug fix ToObject>>() (thanks to sleiN13) 100 | - bug fix CreateStringKeyDictionary() (thanks to John Earnshaw) 101 | - type access optimizations 102 | - test restructuring 103 | 104 | v1.4.12 105 | ------- 106 | - usings cleanup 107 | - bug fix : edge case CreateArray() bt is null -> default to typeof(object) 108 | 109 | v1.4.11 110 | ------- 111 | - added support for char type 112 | - dynamic object processing enhancements (thanks to Justin Dearing) 113 | 114 | v1.4.10 115 | ------- 116 | - added BJSONParameters.SerializerMaxDepth 117 | - speed optimize (thanks to wmjordan) 118 | - added BJSONSerializer.Dispose() to get rid of compiler warnings 119 | 120 | v1.4.9 121 | ------ 122 | - support for multidimensional arrays (thanks to wmjordan) 123 | 124 | v1.4.8 125 | ------ 126 | - bug fix public static properties 127 | 128 | v1.4.7 129 | ------ 130 | - bug fix byte[] keys with Dictionary (thanks to Stanislav Lukeš) 131 | 132 | v1.4.6 133 | ------ 134 | - bug fix serializing static fields and properties 135 | - skip indexer properties on objects (thanks to scymen) 136 | 137 | v1.4.5 138 | ------ 139 | - code sync reflection.cs with fastJSON v2.1.7 140 | 141 | v1.4.4 142 | ------ 143 | - bug fix deserialize private set and no set properties 144 | - added ReadonlyTest() test for the above 145 | 146 | v1.4.3 147 | ------ 148 | - bug fix deserializing a struct property in a class 149 | 150 | v1.4.2 151 | ------ 152 | - bug fix circular references 153 | 154 | v1.4.1 155 | ------ 156 | - bug fix obj.List> and obj.List 157 | - added code intellisense help for methods 158 | - added ClearReflectionCache() to reset all internal structures 159 | 160 | v1.4.0 161 | ------ 162 | - *breaking change* : removed the BJSON.Instance singleton 163 | - moved all the state from BJSON to the Reflection singleton 164 | - all of the BJSON interface is now static 165 | - added BJSONParameters overloads for ToObject() 166 | - support for circular referenced object structures 167 | - added circular test 168 | 169 | v1.3.14.1 170 | --------- 171 | - added ParametricConstructorOverride parameter to control non default constructors 172 | 173 | v1.3.14 174 | ------- 175 | - fixed create enum from value and string 176 | - replaced safedictionary with dictionary for some of the internals so no locks on read 177 | - added custom ignore attributes (Thanks to Jared Thirsk) 178 | - using IsDefined instead of GetCustomAttributes (Thanks to Andrew Rissing) 179 | - moved all the reflection code out of BJSON.cs 180 | - now you can deserialize non default constructor classes (Thanks to Anton Afanasyev) 181 | 182 | v1.3.13 183 | ------- 184 | - fixed working with const properties and fields (i.e ignored) 185 | 186 | v1.3.12 187 | ------- 188 | - bug fix dynamic json and root arrays e.g. [1,2,3,4] 189 | - bug fix objects in array dynamic types e.g. [1,2,{"prop":90}] 190 | - added support for special collections : StringDictionary, NameValueCollection 191 | 192 | v1.3.11 193 | ------- 194 | - added signed assembly 195 | - version numbers will stay at 1.0.0.0 for drop in compatibility 196 | - file version will reflect the build number 197 | - bug fix deserializing to dictionaries instead of dataset when type is not defined 198 | - access inner property in arrays in dynamic types e.g. d.arr[1].a 199 | 200 | v1.3.10 201 | ------- 202 | - fixed hastable deserialize 203 | - added test for hashtable 204 | - changed list of getters to array ~3% performance gain 205 | - removed unused code 206 | 207 | v1.3.9 208 | ------ 209 | - fix dynamic objects and lists 210 | - fix deserialize Dictionary> and Dictionary 211 | - added tests for dictionary with lists 212 | 213 | v1.3.8 214 | ------ 215 | - added serialization of static fields and properties 216 | - fixed disabling extensions in the output 217 | - fixed serializing anonymous types 218 | - added support for dynamic objects 219 | 220 | v1.3.7 221 | ------ 222 | - customtype is now builtin 223 | - added UseUTCTimes property for datetime 224 | - switched to properttype enum instead of booleans 225 | - using switch instead of linked if statements 226 | - unified DynamicMethod between silverlight and full .net 227 | - SafeDictionary lock fixes 228 | 229 | v1.3.6 230 | ------- 231 | - bug fix comma and nulls 232 | - UTC parameter for controlling dates 233 | - unified reflection code with Silverlight4 234 | - locks in SafeDictionary 235 | 236 | v1.3.5 237 | ------ 238 | - added support for root level DataSet and DataTable deserialize (you have to do ToObject(...) ) 239 | - added dataset tests 240 | - added MonoDroid project 241 | 242 | v1.3.4 243 | ------ 244 | - singleton uses ThreadStatic for concurrency (thanks to Philip Jander) 245 | - bug fix extra comma in the output when only 1 property in the object (thanks to Philip Jander) 246 | 247 | v1.3.3 248 | ------ 249 | - bug fix deserialize zero length arrays 250 | - test for German locale numbers 251 | 252 | v1.3.2 253 | ------ 254 | - null object serialize fixed 255 | - added sealed keyword to classes 256 | - bug fix SerializeNullValues=false and an extra comma at the end 257 | - FillObject nested types 258 | 259 | v1.3.1 260 | ------ 261 | - bug fix $types and arrays 262 | - optimize writting $types 263 | 264 | v1.3 265 | ---- 266 | - bug fix reflection code 267 | - added unit tests 268 | - changed ArrayList to List 269 | - updated code to be similar to fastJSON 270 | - deserialize ToObject< Dictionary > 271 | - deserialize ToObject< List > 272 | - added FillObject method 273 | 274 | v1.2 275 | ---- 276 | - refactored reflection code into Reflection class 277 | - added support for top level struct object serialize/deserialize 278 | 279 | v1.1 280 | ---- 281 | - bug fix datetime to local time 282 | - added BJSONParameters 283 | - added global types (reverse format from fastJSON to overcome size limits on name strings) 284 | 285 | v1.0 286 | ---- 287 | - initial release 288 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # fastBinaryJSON 2 | 3 | Binary JSON serializer based on fastJSON 4 | 5 | For a detailed description goto [http://www.codeproject.com/Articles/345070/fastBinaryJSON](http://www.codeproject.com/Articles/345070/fastBinaryJSON) 6 | 7 | --------------------------------------------------------------------------------