This commit is contained in:
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace Newtonsoft.Json.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class AspNetAjaxDateTimeConverterTest
|
||||
{
|
||||
public class DateTimeTestClass
|
||||
{
|
||||
public string PreField;
|
||||
public DateTime DateTimeField;
|
||||
public string PostField;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Serialize()
|
||||
{
|
||||
DateTimeTestClass c = new DateTimeTestClass();
|
||||
c.DateTimeField = new DateTime(2008, 12, 12, 12, 12, 12, 12);
|
||||
c.PreField = "Pre";
|
||||
c.PostField = "Post";
|
||||
|
||||
string json = JavaScriptConvert.SerializeObject(c, new AspNetAjaxDateTimeConverter());
|
||||
|
||||
Assert.AreEqual(@"{""PreField"":""Pre"",""DateTimeField"":""@1229083932012@"",""PostField"":""Post""}", json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeSerialize()
|
||||
{
|
||||
DateTimeTestClass c =
|
||||
JavaScriptConvert.DeserializeObject<DateTimeTestClass>(@"{""PreField"":""Pre"",""DateTimeField"":""@1229083932012@"",""PostField"":""Post""}", new AspNetAjaxDateTimeConverter());
|
||||
|
||||
Assert.AreEqual(new DateTime(2008, 12, 12, 12, 12, 12, 12), c.DateTimeField);
|
||||
Assert.AreEqual("Pre", c.PreField);
|
||||
Assert.AreEqual("Post", c.PostField);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
|
||||
namespace Newtonsoft.Json.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class JsonReaderTest
|
||||
{
|
||||
[Test]
|
||||
public void YahooFinance()
|
||||
{
|
||||
string input = @"{
|
||||
""matches"" : [
|
||||
{""t"":""C"", ""n"":""Citigroup Inc."", ""e"":""NYSE"", ""id"":""662713""}
|
||||
,{""t"":""CHL"", ""n"":""China Mobile Ltd. (ADR)"", ""e"":""NYSE"", ""id"":""660998""}
|
||||
,{""t"":""PTR"", ""n"":""PetroChina Company Limited (ADR)"", ""e"":""NYSE"", ""id"":""664536""}
|
||||
,{""t"":""RIO"", ""n"":""Companhia Vale do Rio Doce (ADR)"", ""e"":""NYSE"", ""id"":""671472""}
|
||||
,{""t"":""RIOPR"", ""n"":""Companhia Vale do Rio Doce (ADR)"", ""e"":""NYSE"", ""id"":""3512643""}
|
||||
,{""t"":""CSCO"", ""n"":""Cisco Systems, Inc."", ""e"":""NASDAQ"", ""id"":""99624""}
|
||||
,{""t"":""CVX"", ""n"":""Chevron Corporation"", ""e"":""NYSE"", ""id"":""667226""}
|
||||
,{""t"":""TM"", ""n"":""Toyota Motor Corporation (ADR)"", ""e"":""NYSE"", ""id"":""655880""}
|
||||
,{""t"":""JPM"", ""n"":""JPMorgan Chase \x26 Co."", ""e"":""NYSE"", ""id"":""665639""}
|
||||
,{""t"":""COP"", ""n"":""ConocoPhillips"", ""e"":""NYSE"", ""id"":""1691168""}
|
||||
,{""t"":""LFC"", ""n"":""China Life Insurance Company Ltd. (ADR)"", ""e"":""NYSE"", ""id"":""688679""}
|
||||
,{""t"":""NOK"", ""n"":""Nokia Corporation (ADR)"", ""e"":""NYSE"", ""id"":""657729""}
|
||||
,{""t"":""KO"", ""n"":""The Coca-Cola Company"", ""e"":""NYSE"", ""id"":""6550""}
|
||||
,{""t"":""VZ"", ""n"":""Verizon Communications Inc."", ""e"":""NYSE"", ""id"":""664887""}
|
||||
,{""t"":""AMX"", ""n"":""America Movil S.A.B de C.V. (ADR)"", ""e"":""NYSE"", ""id"":""665834""}],
|
||||
""all"" : false
|
||||
}
|
||||
";
|
||||
|
||||
using (JsonReader jsonReader = new JsonReader(new StringReader(input)))
|
||||
{
|
||||
while (jsonReader.Read())
|
||||
{
|
||||
Console.WriteLine(jsonReader.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReadingIndented()
|
||||
{
|
||||
string input = @"{
|
||||
CPU: 'Intel',
|
||||
Drives: [
|
||||
'DVD read/writer',
|
||||
""500 gigabyte hard drive""
|
||||
]
|
||||
}";
|
||||
|
||||
StringReader sr = new StringReader(input);
|
||||
|
||||
using (JsonReader jsonReader = new JsonReader(sr))
|
||||
{
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.None);
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.StartObject);
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
|
||||
Assert.AreEqual(jsonReader.Value, "CPU");
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
|
||||
Assert.AreEqual(jsonReader.Value, "Intel");
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
|
||||
Assert.AreEqual(jsonReader.Value, "Drives");
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.StartArray);
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
|
||||
Assert.AreEqual(jsonReader.Value, "DVD read/writer");
|
||||
Assert.AreEqual(jsonReader.QuoteChar, '\'');
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
|
||||
Assert.AreEqual(jsonReader.Value, "500 gigabyte hard drive");
|
||||
Assert.AreEqual(jsonReader.QuoteChar, '"');
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.EndArray);
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.EndObject);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReadingEscapedStrings()
|
||||
{
|
||||
string input = "{value:'Purple\\r \\n monkey\\'s:\\tdishwasher'}";
|
||||
|
||||
StringReader sr = new StringReader(input);
|
||||
|
||||
using (JsonReader jsonReader = new JsonReader(sr))
|
||||
{
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.StartObject);
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
|
||||
Assert.AreEqual(jsonReader.Value, "Purple\r \n monkey's:\tdishwasher");
|
||||
Assert.AreEqual(jsonReader.QuoteChar, '\'');
|
||||
|
||||
jsonReader.Read();
|
||||
Assert.AreEqual(jsonReader.TokenType, JsonToken.EndObject);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReadNewlineLastCharacter()
|
||||
{
|
||||
string input = @"{
|
||||
CPU: 'Intel',
|
||||
Drives: [
|
||||
'DVD read/writer',
|
||||
""500 gigabyte hard drive""
|
||||
]
|
||||
}" + '\n';
|
||||
|
||||
object o = JavaScriptConvert.DeserializeObject(input);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WriteReadWrite()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringWriter sw = new StringWriter(sb);
|
||||
|
||||
using (JsonWriter jsonWriter = new JsonWriter(sw))
|
||||
{
|
||||
jsonWriter.WriteStartArray();
|
||||
jsonWriter.WriteValue(true);
|
||||
|
||||
jsonWriter.WriteStartObject();
|
||||
jsonWriter.WritePropertyName("integer");
|
||||
jsonWriter.WriteValue(99);
|
||||
jsonWriter.WritePropertyName("string");
|
||||
jsonWriter.WriteValue("how now brown cow?");
|
||||
jsonWriter.WritePropertyName("array");
|
||||
|
||||
jsonWriter.WriteStartArray();
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
jsonWriter.WriteValue(i);
|
||||
}
|
||||
|
||||
jsonWriter.WriteStartObject();
|
||||
jsonWriter.WritePropertyName("decimal");
|
||||
jsonWriter.WriteValue(990.00990099m);
|
||||
jsonWriter.WriteEndObject();
|
||||
|
||||
jsonWriter.WriteValue(5);
|
||||
jsonWriter.WriteEndArray();
|
||||
|
||||
jsonWriter.WriteEndObject();
|
||||
|
||||
jsonWriter.WriteValue("This is a string.");
|
||||
jsonWriter.WriteNull();
|
||||
jsonWriter.WriteNull();
|
||||
jsonWriter.WriteEndArray();
|
||||
}
|
||||
|
||||
string json = sb.ToString();
|
||||
|
||||
JsonSerializer serializer = new JsonSerializer();
|
||||
|
||||
object jsonObject = serializer.Deserialize(new JsonReader(new StringReader(json)));
|
||||
|
||||
sb = new StringBuilder();
|
||||
sw = new StringWriter(sb);
|
||||
|
||||
using (JsonWriter jsonWriter = new JsonWriter(sw))
|
||||
{
|
||||
serializer.Serialize(sw, jsonObject);
|
||||
}
|
||||
|
||||
Assert.AreEqual(json, sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,529 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Newtonsoft.Json.Tests
|
||||
{
|
||||
public class Product
|
||||
{
|
||||
public string Name;
|
||||
public DateTime Expiry;
|
||||
public decimal Price;
|
||||
public string[] Sizes;
|
||||
}
|
||||
|
||||
public class Store
|
||||
{
|
||||
public StoreColor Color = StoreColor.Yellow;
|
||||
public DateTime Establised = new DateTime(2010, 1, 22);
|
||||
public double Width = 1.1;
|
||||
public int Employees = 999;
|
||||
public int[] RoomsPerFloor = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
public bool Open = false;
|
||||
public char Symbol = '@';
|
||||
public List<string> Mottos = new List<string>();
|
||||
public decimal Cost = 100980.1M;
|
||||
public string Escape = "\r\n\t\f\b?{\\r\\n\"\'";
|
||||
public List<Product> product = new List<Product>();
|
||||
|
||||
public Store()
|
||||
{
|
||||
Mottos.Add("Hello World");
|
||||
Mottos.Add("öäüÖÄÜ\\'{new Date(12345);}[222]_µ@²³~");
|
||||
Mottos.Add(null);
|
||||
Mottos.Add(" ");
|
||||
|
||||
Product rocket = new Product();
|
||||
rocket.Name = "Rocket";
|
||||
rocket.Expiry = new DateTime(2000, 2, 2, 23, 1, 30);
|
||||
Product alien = new Product();
|
||||
alien.Name = "Alien";
|
||||
|
||||
product.Add(rocket);
|
||||
product.Add(alien);
|
||||
}
|
||||
}
|
||||
|
||||
public enum StoreColor
|
||||
{
|
||||
Black,
|
||||
Red,
|
||||
Yellow,
|
||||
White
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class JsonSerializerTest
|
||||
{
|
||||
[Test]
|
||||
public void PersonTypedObjectDeserialization()
|
||||
{
|
||||
Store store = new Store();
|
||||
|
||||
string jsonText = JavaScriptConvert.SerializeObject(store);
|
||||
|
||||
Store deserializedStore = (Store)JavaScriptConvert.DeserializeObject(jsonText, typeof(Store));
|
||||
|
||||
Console.WriteLine(jsonText);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TypedObjectDeserialization()
|
||||
{
|
||||
Product product = new Product();
|
||||
|
||||
product.Name = "Apple";
|
||||
product.Expiry = new DateTime(2008, 12, 28);
|
||||
product.Price = 3.99M;
|
||||
product.Sizes = new string[] { "Small", "Medium", "Large" };
|
||||
|
||||
string output = JavaScriptConvert.SerializeObject(product);
|
||||
//{
|
||||
// "Name": "Apple",
|
||||
// "Expiry": new Date(1230422400000),
|
||||
// "Price": 3.99,
|
||||
// "Sizes": [
|
||||
// "Small",
|
||||
// "Medium",
|
||||
// "Large"
|
||||
// ]
|
||||
//}
|
||||
|
||||
Product deserializedProduct = (Product)JavaScriptConvert.DeserializeObject(output, typeof(Product));
|
||||
|
||||
Assert.AreEqual("Apple", deserializedProduct.Name);
|
||||
Assert.AreEqual(new DateTime(2008, 12, 28), deserializedProduct.Expiry);
|
||||
Assert.AreEqual(3.99, deserializedProduct.Price);
|
||||
Assert.AreEqual("Small", deserializedProduct.Sizes[0]);
|
||||
Assert.AreEqual("Medium", deserializedProduct.Sizes[1]);
|
||||
Assert.AreEqual("Large", deserializedProduct.Sizes[2]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JavaScriptConvertSerializer()
|
||||
{
|
||||
string value = @"{""Name"":""Orange"", ""Price"":3.99, ""Expiry"":""01/24/2010 12:00:00""}";
|
||||
|
||||
Product p = JavaScriptConvert.DeserializeObject(value, typeof(Product)) as Product;
|
||||
|
||||
Assert.AreEqual("Orange", p.Name);
|
||||
Assert.AreEqual(new DateTime(2010, 1, 24, 12, 0, 0), p.Expiry);
|
||||
Assert.AreEqual(3.99, p.Price);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeJavaScriptDate()
|
||||
{
|
||||
DateTime dateValue = new DateTime(2000, 3, 30);
|
||||
Dictionary<string, object> testDictionary = new Dictionary<string, object>();
|
||||
testDictionary["date"] = dateValue;
|
||||
|
||||
string jsonText = JavaScriptConvert.SerializeObject(testDictionary);
|
||||
|
||||
Dictionary<string, object> deserializedDictionary = (Dictionary<string, object>)JavaScriptConvert.DeserializeObject(jsonText, typeof(Dictionary<string, object>));
|
||||
DateTime deserializedDate = (DateTime)deserializedDictionary["date"];
|
||||
|
||||
Assert.AreEqual(dateValue, deserializedDate);
|
||||
|
||||
Console.WriteLine("DeserializeJavaScriptDate");
|
||||
Console.WriteLine(jsonText);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(jsonText);
|
||||
}
|
||||
|
||||
public class MethodExecutorObject
|
||||
{
|
||||
public string serverClassName;
|
||||
public object[] serverMethodParams;
|
||||
public string clientGetResultFunction;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMethodExecutorObject()
|
||||
{
|
||||
MethodExecutorObject executorObject = new MethodExecutorObject();
|
||||
executorObject.serverClassName = "BanSubs";
|
||||
executorObject.serverMethodParams = new object[] { "21321546", "101", "1236", "D:\\1.txt" };
|
||||
executorObject.clientGetResultFunction = "ClientBanSubsCB";
|
||||
|
||||
string output = JavaScriptConvert.SerializeObject(executorObject);
|
||||
|
||||
MethodExecutorObject executorObject2 = JavaScriptConvert.DeserializeObject(output, typeof(MethodExecutorObject)) as MethodExecutorObject;
|
||||
|
||||
Assert.AreNotSame(executorObject, executorObject2);
|
||||
Assert.AreEqual(executorObject2.serverClassName, "BanSubs");
|
||||
Assert.AreEqual(executorObject2.serverMethodParams.Length, 4);
|
||||
Assert.Contains("101", executorObject2.serverMethodParams);
|
||||
Assert.AreEqual(executorObject2.clientGetResultFunction, "ClientBanSubsCB");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HashtableDeserialization()
|
||||
{
|
||||
string value = @"{""Name"":""Orange"", ""Price"":3.99, ""Expiry"":""01/24/2010 12:00:00""}";
|
||||
|
||||
Hashtable p = JavaScriptConvert.DeserializeObject(value, typeof(Hashtable)) as Hashtable;
|
||||
|
||||
Assert.AreEqual("Orange", p["Name"].ToString());
|
||||
}
|
||||
|
||||
public class TypedSubHashtable
|
||||
{
|
||||
public string Name;
|
||||
public Hashtable Hash;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TypedHashtableDeserialization()
|
||||
{
|
||||
string value = @"{""Name"":""Orange"", ""Hash"":{""Expiry"":""01/24/2010 12:00:00""}}";
|
||||
|
||||
TypedSubHashtable p = JavaScriptConvert.DeserializeObject(value, typeof(TypedSubHashtable)) as TypedSubHashtable;
|
||||
|
||||
Assert.AreEqual("01/24/2010 12:00:00", p.Hash["Expiry"].ToString());
|
||||
}
|
||||
|
||||
public class GetOnlyPropertyClass
|
||||
{
|
||||
public string Field = "Field";
|
||||
|
||||
public string GetOnlyProperty
|
||||
{
|
||||
get { return "GetOnlyProperty"; }
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializeDeserializeGetOnlyProperty()
|
||||
{
|
||||
string value = JavaScriptConvert.SerializeObject(new GetOnlyPropertyClass());
|
||||
|
||||
GetOnlyPropertyClass c = JavaScriptConvert.DeserializeObject<GetOnlyPropertyClass>(value);
|
||||
|
||||
Assert.AreEqual(c.Field, "Field");
|
||||
Assert.AreEqual(c.GetOnlyProperty, "GetOnlyProperty");
|
||||
}
|
||||
|
||||
public class SetOnlyPropertyClass
|
||||
{
|
||||
public string Field = "Field";
|
||||
|
||||
public string SetOnlyProperty
|
||||
{
|
||||
set { }
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializeDeserializeSetOnlyProperty()
|
||||
{
|
||||
string value = JavaScriptConvert.SerializeObject(new SetOnlyPropertyClass());
|
||||
|
||||
SetOnlyPropertyClass c = JavaScriptConvert.DeserializeObject<SetOnlyPropertyClass>(value);
|
||||
|
||||
Assert.AreEqual(c.Field, "Field");
|
||||
}
|
||||
|
||||
public class JsonIgnoreAttributeTestClass
|
||||
{
|
||||
private int _property = 21;
|
||||
private int _ignoredProperty = 12;
|
||||
|
||||
public int Field;
|
||||
public int Property
|
||||
{
|
||||
get { return _property; }
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public int IgnoredField;
|
||||
|
||||
[JsonIgnore]
|
||||
public int IgnoredProperty
|
||||
{
|
||||
get { return _ignoredProperty; }
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonIgnoreAttributeTest()
|
||||
{
|
||||
string json = JavaScriptConvert.SerializeObject(new JsonIgnoreAttributeTestClass());
|
||||
|
||||
Assert.AreEqual(@"{""Field"":0,""Property"":21}", json);
|
||||
|
||||
JsonIgnoreAttributeTestClass c = JavaScriptConvert.DeserializeObject<JsonIgnoreAttributeTestClass>(@"{""Field"":99,""Property"":-1,""IgnoredField"":-1}");
|
||||
|
||||
Assert.AreEqual(0, c.IgnoredField);
|
||||
Assert.AreEqual(99, c.Field);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GoogleSearchAPI()
|
||||
{
|
||||
string json = @"{
|
||||
results:
|
||||
[
|
||||
{
|
||||
GsearchResultClass:""GwebSearch"",
|
||||
unescapedUrl : ""http://www.google.com/"",
|
||||
url : ""http://www.google.com/"",
|
||||
visibleUrl : ""www.google.com"",
|
||||
cacheUrl :
|
||||
""http://www.google.com/search?q=cache:zhool8dxBV4J:www.google.com"",
|
||||
title : ""Google"",
|
||||
titleNoFormatting : ""Google"",
|
||||
content : ""Enables users to search the Web, Usenet, and
|
||||
images. Features include PageRank, caching and translation of
|
||||
results, and an option to find similar pages.""
|
||||
},
|
||||
{
|
||||
GsearchResultClass:""GwebSearch"",
|
||||
unescapedUrl : ""http://news.google.com/"",
|
||||
url : ""http://news.google.com/"",
|
||||
visibleUrl : ""news.google.com"",
|
||||
cacheUrl :
|
||||
""http://www.google.com/search?q=cache:Va_XShOz_twJ:news.google.com"",
|
||||
title : ""Google News"",
|
||||
titleNoFormatting : ""Google News"",
|
||||
content : ""Aggregated headlines and a search engine of many of the world's news sources.""
|
||||
},
|
||||
|
||||
{
|
||||
GsearchResultClass:""GwebSearch"",
|
||||
unescapedUrl : ""http://groups.google.com/"",
|
||||
url : ""http://groups.google.com/"",
|
||||
visibleUrl : ""groups.google.com"",
|
||||
cacheUrl :
|
||||
""http://www.google.com/search?q=cache:x2uPD3hfkn0J:groups.google.com"",
|
||||
title : ""Google Groups"",
|
||||
titleNoFormatting : ""Google Groups"",
|
||||
content : ""Enables users to search and browse the Usenet
|
||||
archives which consist of over 700 million messages, and post new
|
||||
comments.""
|
||||
},
|
||||
|
||||
{
|
||||
GsearchResultClass:""GwebSearch"",
|
||||
unescapedUrl : ""http://maps.google.com/"",
|
||||
url : ""http://maps.google.com/"",
|
||||
visibleUrl : ""maps.google.com"",
|
||||
cacheUrl :
|
||||
""http://www.google.com/search?q=cache:dkf5u2twBXIJ:maps.google.com"",
|
||||
title : ""Google Maps"",
|
||||
titleNoFormatting : ""Google Maps"",
|
||||
content : ""Provides directions, interactive maps, and
|
||||
satellite/aerial imagery of the United States. Can also search by
|
||||
keyword such as type of business.""
|
||||
}
|
||||
],
|
||||
|
||||
adResults:
|
||||
[
|
||||
{
|
||||
GsearchResultClass:""GwebSearch.ad"",
|
||||
title : ""Gartner Symposium/ITxpo"",
|
||||
content1 : ""Meet brilliant Gartner IT analysts"",
|
||||
content2 : ""20-23 May 2007- Barcelona, Spain"",
|
||||
url :
|
||||
""http://www.google.com/url?sa=L&ai=BVualExYGRo3hD5ianAPJvejjD8-s6ye7kdTwArbI4gTAlrECEAEYASDXtMMFOAFQubWAjvr_____AWDXw_4EiAEBmAEAyAEBgAIB&num=1&q=http://www.gartner.com/it/sym/2007/spr8/spr8.jsp%3Fsrc%3D_spain_07_%26WT.srch%3D1&usg=__CxRH06E4Xvm9Muq13S4MgMtnziY="",
|
||||
|
||||
impressionUrl :
|
||||
""http://www.google.com/uds/css/ad-indicator-on.gif?ai=BVualExYGRo3hD5ianAPJvejjD8-s6ye7kdTwArbI4gTAlrECEAEYASDXtMMFOAFQubWAjvr_____AWDXw_4EiAEBmAEAyAEBgAIB"",
|
||||
|
||||
unescapedUrl :
|
||||
""http://www.google.com/url?sa=L&ai=BVualExYGRo3hD5ianAPJvejjD8-s6ye7kdTwArbI4gTAlrECEAEYASDXtMMFOAFQubWAjvr_____AWDXw_4EiAEBmAEAyAEBgAIB&num=1&q=http://www.gartner.com/it/sym/2007/spr8/spr8.jsp%3Fsrc%3D_spain_07_%26WT.srch%3D1&usg=__CxRH06E4Xvm9Muq13S4MgMtnziY="",
|
||||
|
||||
visibleUrl : ""www.gartner.com""
|
||||
}
|
||||
]
|
||||
}
|
||||
";
|
||||
object o = JavaScriptConvert.DeserializeObject(json);
|
||||
string s = string.Empty;
|
||||
s += s;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TorrentDeserializeTest()
|
||||
{
|
||||
string jsonText = @"{
|
||||
"""":"""",
|
||||
""label"": [
|
||||
[""SomeName"",6]
|
||||
],
|
||||
""torrents"": [
|
||||
[""192D99A5C943555CB7F00A852821CF6D6DB3008A"",201,""filename.avi"",178311826,1000,178311826,72815250,408,1603,7,121430,""NameOfLabelPrevioslyDefined"",3,6,0,8,128954,-1,0],
|
||||
],
|
||||
""torrentc"": ""1816000723""
|
||||
}";
|
||||
|
||||
JavaScriptObject o = (JavaScriptObject)JavaScriptConvert.DeserializeObject(jsonText);
|
||||
Assert.AreEqual(4, o.Count);
|
||||
|
||||
JavaScriptArray torrentsArray = (JavaScriptArray)o["torrents"];
|
||||
JavaScriptArray nestedTorrentsArray = (JavaScriptArray)torrentsArray[0];
|
||||
Assert.AreEqual(nestedTorrentsArray.Count, 19);
|
||||
}
|
||||
|
||||
public class JsonPropertyClass
|
||||
{
|
||||
[JsonProperty("pie")]
|
||||
public string Pie = "Yum";
|
||||
|
||||
[JsonIgnore]
|
||||
public string pie = "No pie for you!";
|
||||
|
||||
public string pie1 = "PieChart!";
|
||||
|
||||
private int _sweetCakesCount;
|
||||
|
||||
[JsonProperty("sweet_cakes_count")]
|
||||
public int SweetCakesCount
|
||||
{
|
||||
get { return _sweetCakesCount; }
|
||||
set { _sweetCakesCount = value; }
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonPropertyClassSerialize()
|
||||
{
|
||||
JsonPropertyClass test = new JsonPropertyClass();
|
||||
test.Pie = "Delicious";
|
||||
test.SweetCakesCount = int.MaxValue;
|
||||
|
||||
string jsonText = JavaScriptConvert.SerializeObject(test);
|
||||
|
||||
Assert.AreEqual(@"{""pie"":""Delicious"",""pie1"":""PieChart!"",""sweet_cakes_count"":2147483647}", jsonText);
|
||||
|
||||
JsonPropertyClass test2 = JavaScriptConvert.DeserializeObject<JsonPropertyClass>(jsonText);
|
||||
|
||||
Assert.AreEqual(test.Pie, test2.Pie);
|
||||
Assert.AreEqual(test.SweetCakesCount, test2.SweetCakesCount);
|
||||
}
|
||||
|
||||
public class BadJsonPropertyClass
|
||||
{
|
||||
[JsonProperty("pie")]
|
||||
public string Pie = "Yum";
|
||||
|
||||
public string pie = "PieChart!";
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(JsonSerializationException), ExpectedMessage = @"A member with the name 'pie' already exists on Newtonsoft.Json.Tests.JsonSerializerTest+BadJsonPropertyClass. Use the JsonPropertyAttribute to specify another name.")]
|
||||
public void BadJsonPropertyClassSerialize()
|
||||
{
|
||||
JavaScriptConvert.SerializeObject(new BadJsonPropertyClass());
|
||||
}
|
||||
|
||||
public class Article
|
||||
{
|
||||
public string Name;
|
||||
|
||||
public Article()
|
||||
{
|
||||
}
|
||||
|
||||
public Article(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public class ArticleCollection : List<Article>
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InheritedListSerialize()
|
||||
{
|
||||
Article a1 = new Article("a1");
|
||||
Article a2 = new Article("a2");
|
||||
|
||||
ArticleCollection articles1 = new ArticleCollection();
|
||||
articles1.Add(a1);
|
||||
articles1.Add(a2);
|
||||
|
||||
string jsonText = JavaScriptConvert.SerializeObject(articles1);
|
||||
|
||||
ArticleCollection articles2 = JavaScriptConvert.DeserializeObject<ArticleCollection>(jsonText);
|
||||
|
||||
Assert.AreEqual(articles1.Count, articles2.Count);
|
||||
Assert.AreEqual(articles1[0].Name, articles2[0].Name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReadOnlyCollectionSerialize()
|
||||
{
|
||||
ReadOnlyCollection<int> r1 = new ReadOnlyCollection<int>(new int[] {0, 1, 2, 3, 4});
|
||||
|
||||
string jsonText = JavaScriptConvert.SerializeObject(r1);
|
||||
|
||||
ReadOnlyCollection<int> r2 = JavaScriptConvert.DeserializeObject<ReadOnlyCollection<int>>(jsonText);
|
||||
|
||||
CollectionAssert.AreEqual(r1, r2);
|
||||
}
|
||||
|
||||
//public abstract class Foo
|
||||
//{
|
||||
//}
|
||||
|
||||
//public class Baz : Foo
|
||||
//{
|
||||
//}
|
||||
|
||||
//public class Bar : Foo
|
||||
//{
|
||||
//}
|
||||
|
||||
//public class BazJsonConverter : JsonConverter
|
||||
//{
|
||||
// public override bool CanConvert(Type objectType)
|
||||
// {
|
||||
// throw new Exception("The method or operation is not implemented.");
|
||||
// }
|
||||
//}
|
||||
|
||||
//public class BarJsonConverter : JsonConverter
|
||||
//{
|
||||
// public override bool CanConvert(Type objectType)
|
||||
// {
|
||||
// throw new Exception("The method or operation is not implemented.");
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
|
||||
namespace Newtonsoft.Json.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class JsonWriterTest
|
||||
{
|
||||
[Test]
|
||||
public void ValueFormatting()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringWriter sw = new StringWriter(sb);
|
||||
|
||||
using (JsonWriter jsonWriter = new JsonWriter(sw))
|
||||
{
|
||||
jsonWriter.WriteStartArray();
|
||||
jsonWriter.WriteValue('@');
|
||||
jsonWriter.WriteValue("\r\n\t\f\b?{\\r\\n\"\'");
|
||||
jsonWriter.WriteValue(true);
|
||||
jsonWriter.WriteValue(10);
|
||||
jsonWriter.WriteValue(10.99);
|
||||
jsonWriter.WriteValue(0.99);
|
||||
jsonWriter.WriteValue(0.000000000000000001d);
|
||||
jsonWriter.WriteValue(0.000000000000000001m);
|
||||
jsonWriter.WriteValue(null);
|
||||
jsonWriter.WriteValue("This is a string.");
|
||||
jsonWriter.WriteNull();
|
||||
jsonWriter.WriteUndefined();
|
||||
jsonWriter.WriteEndArray();
|
||||
}
|
||||
|
||||
string expected = @"[""@"",""\r\n\t\f\b?{\\r\\n\""'"",true,10,10.99,0.99,1E-18,0.000000000000000001,"""",""This is a string."",null,undefined]";
|
||||
string result = sb.ToString();
|
||||
|
||||
Console.WriteLine("ValueFormatting");
|
||||
Console.WriteLine(result);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StringEscaping()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringWriter sw = new StringWriter(sb);
|
||||
|
||||
using (JsonWriter jsonWriter = new JsonWriter(sw))
|
||||
{
|
||||
jsonWriter.WriteStartArray();
|
||||
jsonWriter.WriteValue(@"""These pretzels are making me thirsty!""");
|
||||
jsonWriter.WriteValue("Jeff's house was burninated.");
|
||||
jsonWriter.WriteValue(@"1. You don't talk about fight club.
|
||||
2. You don't talk about fight club.");
|
||||
jsonWriter.WriteValue("35% of\t statistics\n are made\r up.");
|
||||
jsonWriter.WriteEndArray();
|
||||
}
|
||||
|
||||
string expected = @"[""\""These pretzels are making me thirsty!\"""",""Jeff's house was burninated."",""1. You don't talk about fight club.\r\n2. You don't talk about fight club."",""35% of\t statistics\n are made\r up.""]";
|
||||
string result = sb.ToString();
|
||||
|
||||
Console.WriteLine("StringEscaping");
|
||||
Console.WriteLine(result);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Indenting()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringWriter sw = new StringWriter(sb);
|
||||
|
||||
using (JsonWriter jsonWriter = new JsonWriter(sw))
|
||||
{
|
||||
jsonWriter.Formatting = Formatting.Indented;
|
||||
|
||||
jsonWriter.WriteStartObject();
|
||||
jsonWriter.WritePropertyName("CPU");
|
||||
jsonWriter.WriteValue("Intel");
|
||||
jsonWriter.WritePropertyName("PSU");
|
||||
jsonWriter.WriteValue("500W");
|
||||
jsonWriter.WritePropertyName("Drives");
|
||||
jsonWriter.WriteStartArray();
|
||||
jsonWriter.WriteValue("DVD read/writer");
|
||||
jsonWriter.WriteComment("(broken)");
|
||||
jsonWriter.WriteValue("500 gigabyte hard drive");
|
||||
jsonWriter.WriteValue("200 gigabype hard drive");
|
||||
jsonWriter.WriteEnd();
|
||||
jsonWriter.WriteEndObject();
|
||||
}
|
||||
|
||||
string expected = @"{
|
||||
""CPU"": ""Intel"",
|
||||
""PSU"": ""500W"",
|
||||
""Drives"": [
|
||||
""DVD read/writer""
|
||||
/*(broken)*/,
|
||||
""500 gigabyte hard drive"",
|
||||
""200 gigabype hard drive""
|
||||
]
|
||||
}";
|
||||
string result = sb.ToString();
|
||||
|
||||
Console.WriteLine("Indenting");
|
||||
Console.WriteLine(result);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void State()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringWriter sw = new StringWriter(sb);
|
||||
|
||||
using (JsonWriter jsonWriter = new JsonWriter(sw))
|
||||
{
|
||||
Assert.AreEqual(WriteState.Start, jsonWriter.WriteState);
|
||||
|
||||
jsonWriter.WriteStartObject();
|
||||
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
|
||||
|
||||
jsonWriter.WritePropertyName("CPU");
|
||||
Assert.AreEqual(WriteState.Property, jsonWriter.WriteState);
|
||||
|
||||
jsonWriter.WriteValue("Intel");
|
||||
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
|
||||
|
||||
jsonWriter.WritePropertyName("Drives");
|
||||
Assert.AreEqual(WriteState.Property, jsonWriter.WriteState);
|
||||
|
||||
jsonWriter.WriteStartArray();
|
||||
Assert.AreEqual(WriteState.Array, jsonWriter.WriteState);
|
||||
|
||||
jsonWriter.WriteValue("DVD read/writer");
|
||||
Assert.AreEqual(WriteState.Array, jsonWriter.WriteState);
|
||||
|
||||
jsonWriter.WriteEnd();
|
||||
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
|
||||
|
||||
jsonWriter.WriteEndObject();
|
||||
Assert.AreEqual(WriteState.Start, jsonWriter.WriteState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{3E6E2335-B079-4B5B-A65A-9D586914BCBB}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Newtonsoft.Json.Tests</RootNamespace>
|
||||
<AssemblyName>Newtonsoft.Json.Tests</AssemblyName>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="nunit.framework, Version=2.4.3.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Lib\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AspNetAjaxDateTimeConverterTest.cs" />
|
||||
<Compile Include="JsonReaderTest.cs" />
|
||||
<Compile Include="JsonSerializerTest.cs" />
|
||||
<Compile Include="JsonWriterTest.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="XmlNodeConverterTest.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Newtonsoft.Json\Newtonsoft.Json.csproj">
|
||||
<Project>{A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}</Project>
|
||||
<Name>Newtonsoft.Json</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Newtonsoft Json.NET Test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Newtonsoft")]
|
||||
[assembly: AssemblyProduct("Newtonsoft Json.NET Test")]
|
||||
[assembly: AssemblyCopyright("Copyright © Newtonsoft 2006")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("0be3d72b-d2ef-409c-985c-d3ede89a25f1")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.3.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.3.0.0")]
|
||||
@@ -0,0 +1,342 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace Newtonsoft.Json.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class XmlNodeConverterTest
|
||||
{
|
||||
[Test]
|
||||
public void DocumentSerializeIndented()
|
||||
{
|
||||
string xml = @"<?xml version=""1.0"" standalone=""no""?>
|
||||
<?xml-stylesheet href=""classic.xsl"" type=""text/xml""?>
|
||||
<span class=""vevent"">
|
||||
<a class=""url"" href=""http://www.web2con.com/"">
|
||||
<span class=""summary"">Web 2.0 Conference<![CDATA[my escaped text]]></span>
|
||||
<abbr class=""dtstart"" title=""2005-10-05"">October 5</abbr>
|
||||
<abbr class=""dtend"" title=""2005-10-08"">7</abbr>
|
||||
<span class=""location"">Argent Hotel, San Francisco, CA</span>
|
||||
</a>
|
||||
</span>";
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(xml);
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
|
||||
using (JsonWriter jsonWriter = new JsonWriter(sw))
|
||||
{
|
||||
jsonWriter.Formatting = Formatting.Indented;
|
||||
|
||||
JsonSerializer jsonSerializer = new JsonSerializer();
|
||||
jsonSerializer.Converters.Add(new XmlNodeConverter());
|
||||
|
||||
jsonSerializer.Serialize(jsonWriter, doc);
|
||||
}
|
||||
|
||||
string jsonText = sw.ToString();
|
||||
string expected = @"{
|
||||
""?xml"": {
|
||||
""@version"": ""1.0"",
|
||||
""@standalone"": ""no""
|
||||
},
|
||||
""?xml-stylesheet"": ""href=\""classic.xsl\"" type=\""text/xml\"""",
|
||||
""span"": {
|
||||
""@class"": ""vevent"",
|
||||
""a"": {
|
||||
""@class"": ""url"",
|
||||
""@href"": ""http://www.web2con.com/"",
|
||||
""span"": [
|
||||
{
|
||||
""@class"": ""summary"",
|
||||
""#text"": ""Web 2.0 Conference"",
|
||||
""#cdata-section"": ""my escaped text""
|
||||
},
|
||||
{
|
||||
""@class"": ""location"",
|
||||
""#text"": ""Argent Hotel, San Francisco, CA""
|
||||
}
|
||||
],
|
||||
""abbr"": [
|
||||
{
|
||||
""@class"": ""dtstart"",
|
||||
""@title"": ""2005-10-05"",
|
||||
""#text"": ""October 5""
|
||||
},
|
||||
{
|
||||
""@class"": ""dtend"",
|
||||
""@title"": ""2005-10-08"",
|
||||
""#text"": ""7""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
Assert.AreEqual(expected, jsonText);
|
||||
|
||||
Console.WriteLine("DocumentSerializeIndented");
|
||||
Console.WriteLine(jsonText);
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SerializeNodeTypes()
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
string jsonText;
|
||||
|
||||
Console.WriteLine("SerializeNodeTypes");
|
||||
|
||||
// XmlAttribute
|
||||
XmlAttribute attribute = doc.CreateAttribute("msdata:IsDataSet");
|
||||
attribute.Value = "true";
|
||||
|
||||
jsonText = JavaScriptConvert.SerializeXmlNode(attribute);
|
||||
|
||||
Console.WriteLine(jsonText);
|
||||
Assert.AreEqual(@"{""@msdata:IsDataSet"":""true""}", jsonText);
|
||||
|
||||
|
||||
// XmlProcessingInstruction
|
||||
XmlProcessingInstruction instruction = doc.CreateProcessingInstruction("xml-stylesheet", @"href=""classic.xsl"" type=""text/xml""");
|
||||
|
||||
jsonText = JavaScriptConvert.SerializeXmlNode(instruction);
|
||||
|
||||
Console.WriteLine(jsonText);
|
||||
Assert.AreEqual(@"{""?xml-stylesheet"":""href=\""classic.xsl\"" type=\""text/xml\""""}", jsonText);
|
||||
|
||||
|
||||
// XmlProcessingInstruction
|
||||
XmlCDataSection cDataSection = doc.CreateCDataSection("<Kiwi>true</Kiwi>");
|
||||
|
||||
jsonText = JavaScriptConvert.SerializeXmlNode(cDataSection);
|
||||
|
||||
Console.WriteLine(jsonText);
|
||||
Assert.AreEqual(@"{""#cdata-section"":""<Kiwi>true</Kiwi>""}", jsonText);
|
||||
|
||||
|
||||
// XmlElement
|
||||
XmlElement element = doc.CreateElement("xs:Choice");
|
||||
element.SetAttributeNode(attribute);
|
||||
|
||||
element.AppendChild(instruction);
|
||||
element.AppendChild(cDataSection);
|
||||
|
||||
jsonText = JavaScriptConvert.SerializeXmlNode(element);
|
||||
|
||||
Console.WriteLine(jsonText);
|
||||
Assert.AreEqual(@"{""xs:Choice"":{""@msdata:IsDataSet"":""true"",""?xml-stylesheet"":""href=\""classic.xsl\"" type=\""text/xml\"""",""#cdata-section"":""<Kiwi>true</Kiwi>""}}", jsonText);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DocumentFragmentSerialize()
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
|
||||
XmlDocumentFragment fragement = doc.CreateDocumentFragment();
|
||||
|
||||
fragement.InnerXml = "<Item>widget</Item><Item>widget</Item>";
|
||||
|
||||
string jsonText = JavaScriptConvert.SerializeXmlNode(fragement);
|
||||
|
||||
string expected = @"{""Item"":[""widget"",""widget""]}";
|
||||
|
||||
Assert.AreEqual(expected, jsonText);
|
||||
|
||||
Console.WriteLine("DocumentFragmentSerialize");
|
||||
Console.WriteLine(jsonText);
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NamespaceSerializeDeserialize()
|
||||
{
|
||||
string xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
|
||||
<xs:schema xs:id=""SomeID""
|
||||
xmlns=""""
|
||||
xmlns:xs=""http://www.w3.org/2001/XMLSchema""
|
||||
xmlns:msdata=""urn:schemas-microsoft-com:xml-msdata"">
|
||||
<xs:element name=""MyDataSet"" msdata:IsDataSet=""true"">
|
||||
<xs:complexType>
|
||||
<xs:choice maxOccurs=""unbounded"">
|
||||
<xs:element name=""customers"" >
|
||||
<xs:complexType >
|
||||
<xs:sequence>
|
||||
<xs:element name=""CustomerID"" type=""xs:integer""
|
||||
minOccurs=""0"" />
|
||||
<xs:element name=""CompanyName"" type=""xs:string""
|
||||
minOccurs=""0"" />
|
||||
<xs:element name=""Phone"" type=""xs:string"" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>";
|
||||
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(xml);
|
||||
|
||||
string jsonText = JavaScriptConvert.SerializeXmlNode(doc);
|
||||
|
||||
XmlDocument deserializedDoc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);
|
||||
|
||||
Assert.AreEqual(doc.InnerXml, deserializedDoc.InnerXml);
|
||||
|
||||
Console.WriteLine("NamespaceSerializeDeserialize");
|
||||
Console.WriteLine(jsonText);
|
||||
Console.WriteLine(deserializedDoc.InnerXml);
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DocumentDeserialize()
|
||||
{
|
||||
string jsonText = @"{
|
||||
""?xml"": {
|
||||
""@version"": ""1.0"",
|
||||
""@standalone"": ""no""
|
||||
},
|
||||
""span"": {
|
||||
""@class"": ""vevent"",
|
||||
""a"": {
|
||||
""@class"": ""url"",
|
||||
""@href"": ""http://www.web2con.com/"",
|
||||
""span"": {
|
||||
""@class"": ""summary"",
|
||||
""#text"": ""Web 2.0 Conference"",
|
||||
""#cdata-section"": ""my escaped text""
|
||||
}
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
XmlDocument doc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);
|
||||
|
||||
string expected = @"<?xml version=""1.0"" standalone=""no""?>
|
||||
<span class=""vevent"">
|
||||
<a class=""url"" href=""http://www.web2con.com/"">
|
||||
<span class=""summary"">Web 2.0 Conference<![CDATA[my escaped text]]></span>
|
||||
</a>
|
||||
</span>";
|
||||
|
||||
string formattedXml = GetIndentedInnerXml(doc);
|
||||
|
||||
Console.WriteLine("DocumentDeserialize");
|
||||
Console.WriteLine(formattedXml);
|
||||
Console.WriteLine();
|
||||
|
||||
Assert.AreEqual(expected, formattedXml);
|
||||
}
|
||||
|
||||
private string GetIndentedInnerXml(XmlNode node)
|
||||
{
|
||||
XmlWriterSettings settings = new XmlWriterSettings();
|
||||
settings.Indent = true;
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
|
||||
using (XmlWriter writer = XmlWriter.Create(sw, settings))
|
||||
{
|
||||
node.WriteTo(writer);
|
||||
}
|
||||
|
||||
return sw.ToString();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SingleTextNode()
|
||||
{
|
||||
string xml = @"<?xml version=""1.0"" standalone=""no""?>
|
||||
<root>
|
||||
<person id=""1"">
|
||||
<name>Alan</name>
|
||||
<url>http://www.google.com</url>
|
||||
</person>
|
||||
<person id=""2"">
|
||||
<name>Louis</name>
|
||||
<url>http://www.yahoo.com</url>
|
||||
</person>
|
||||
</root>";
|
||||
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(xml);
|
||||
|
||||
string jsonText = JavaScriptConvert.SerializeXmlNode(doc);
|
||||
|
||||
XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);
|
||||
|
||||
Assert.AreEqual(doc.InnerXml, newDoc.InnerXml);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmptyNode()
|
||||
{
|
||||
string xml = @"<?xml version=""1.0"" standalone=""no""?>
|
||||
<root>
|
||||
<person id=""1"">
|
||||
<name>Alan</name>
|
||||
<url />
|
||||
</person>
|
||||
<person id=""2"">
|
||||
<name>Louis</name>
|
||||
<url>http://www.yahoo.com</url>
|
||||
</person>
|
||||
</root>";
|
||||
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(xml);
|
||||
|
||||
string jsonText = JavaScriptConvert.SerializeXmlNode(doc);
|
||||
|
||||
Console.WriteLine(jsonText);
|
||||
|
||||
XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);
|
||||
|
||||
Assert.AreEqual(doc.InnerXml, newDoc.InnerXml);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OtherElementDataTypes()
|
||||
{
|
||||
string jsonText = @"{""?xml"":{""@version"":""1.0"",""@standalone"":""no""},""root"":{""person"":[{""@id"":""1"",""Float"":2.5,""Integer"":99},{""@id"":""2"",""Boolean"":true,""date"":new Date(954374400000)}]}}";
|
||||
|
||||
XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);
|
||||
|
||||
string expected = @"<?xml version=""1.0"" standalone=""no""?><root><person id=""1""><Float>2.5</Float><Integer>99</Integer></person><person id=""2""><Boolean>true</Boolean><date>2000-03-30T00:00:00.0000000+12:00</date></person></root>";
|
||||
|
||||
Assert.AreEqual(expected, newDoc.InnerXml);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Newtonsoft.Json", "Newtonsoft.Json\Newtonsoft.Json.csproj", "{A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}"
|
||||
ProjectSection(WebsiteProperties) = preProject
|
||||
Debug.AspNetCompiler.Debug = "True"
|
||||
Release.AspNetCompiler.Debug = "False"
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lib", "Lib", "{620042D9-2753-48F5-BEDE-3905248781D2}"
|
||||
ProjectSection(WebsiteProperties) = preProject
|
||||
Debug.AspNetCompiler.Debug = "True"
|
||||
Release.AspNetCompiler.Debug = "False"
|
||||
EndProjectSection
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Lib\nunit.framework.dll = Lib\nunit.framework.dll
|
||||
Lib\nunit.framework.xml = Lib\nunit.framework.xml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Newtonsoft.Json.Tests", "Newtonsoft.Json.Tests\Newtonsoft.Json.Tests.csproj", "{3E6E2335-B079-4B5B-A65A-9D586914BCBB}"
|
||||
ProjectSection(WebsiteProperties) = preProject
|
||||
Debug.AspNetCompiler.Debug = "True"
|
||||
Release.AspNetCompiler.Debug = "False"
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3E6E2335-B079-4B5B-A65A-9D586914BCBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3E6E2335-B079-4B5B-A65A-9D586914BCBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3E6E2335-B079-4B5B-A65A-9D586914BCBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3E6E2335-B079-4B5B-A65A-9D586914BCBB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,59 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Converters
|
||||
{
|
||||
public class AspNetAjaxDateTimeConverter : JsonConverter
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, object value)
|
||||
{
|
||||
DateTime dateTime = (DateTime)value;
|
||||
long javaScriptTicks = JavaScriptConvert.ConvertDateTimeToJavaScriptTicks(dateTime);
|
||||
|
||||
writer.WriteValue("@" + javaScriptTicks.ToString(null, CultureInfo.InvariantCulture) + "@");
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType)
|
||||
{
|
||||
string dateTimeText = (string)reader.Value;
|
||||
dateTimeText = dateTimeText.Substring(1, dateTimeText.Length - 2);
|
||||
|
||||
long javaScriptTicks = Convert.ToInt64(dateTimeText);
|
||||
|
||||
return JavaScriptConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
|
||||
}
|
||||
|
||||
public override bool CanConvert(Type valueType)
|
||||
{
|
||||
return typeof(DateTime).IsAssignableFrom(valueType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Newtonsoft.Json.Converters
|
||||
{
|
||||
public class HtmlColorConverter : JsonConverter
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, object value)
|
||||
{
|
||||
writer.WriteValue(ColorTranslator.ToHtml((Color)value));
|
||||
}
|
||||
|
||||
public override bool CanConvert(Type valueType)
|
||||
{
|
||||
return typeof(Color).IsAssignableFrom(valueType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,472 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Xml;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
|
||||
namespace Newtonsoft.Json.Converters
|
||||
{
|
||||
public class XmlNodeConverter : JsonConverter
|
||||
{
|
||||
private const string TextName = "#text";
|
||||
private const string CommentName = "#comment";
|
||||
private const string CDataName = "#cdata-section";
|
||||
private const string WhitespaceName = "#whitespace";
|
||||
private const string SignificantWhitespaceName = "#significant-whitespace";
|
||||
private const string DeclarationName = "?xml";
|
||||
|
||||
#region Writing
|
||||
public override void WriteJson(JsonWriter writer, object value)
|
||||
{
|
||||
XmlNode node = value as XmlNode;
|
||||
|
||||
if (node == null)
|
||||
throw new ArgumentException("Value must be an XmlNode", "value");
|
||||
|
||||
writer.WriteStartObject();
|
||||
SerializeNode(writer, node, true);
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
private string GetPropertyName(XmlNode node)
|
||||
{
|
||||
switch (node.NodeType)
|
||||
{
|
||||
case XmlNodeType.Attribute:
|
||||
return "@" + node.Name;
|
||||
case XmlNodeType.CDATA:
|
||||
return CDataName;
|
||||
case XmlNodeType.Comment:
|
||||
return CommentName;
|
||||
case XmlNodeType.Element:
|
||||
return node.Name;
|
||||
case XmlNodeType.ProcessingInstruction:
|
||||
return "?" + node.Name;
|
||||
case XmlNodeType.XmlDeclaration:
|
||||
return DeclarationName;
|
||||
case XmlNodeType.SignificantWhitespace:
|
||||
return SignificantWhitespaceName;
|
||||
case XmlNodeType.Text:
|
||||
return TextName;
|
||||
case XmlNodeType.Whitespace:
|
||||
return WhitespaceName;
|
||||
default:
|
||||
throw new JsonSerializationException("Unexpected XmlNodeType when getting node name: " + node.NodeType);
|
||||
}
|
||||
}
|
||||
|
||||
private void SerializeGroupedNodes(JsonWriter writer, XmlNode node)
|
||||
{
|
||||
// group nodes together by name
|
||||
Dictionary<string, List<XmlNode>> nodesGroupedByName = new Dictionary<string, List<XmlNode>>();
|
||||
|
||||
for (int i = 0; i < node.ChildNodes.Count; i++)
|
||||
{
|
||||
XmlNode childNode = node.ChildNodes[i];
|
||||
string nodeName = GetPropertyName(childNode);
|
||||
|
||||
List<XmlNode> nodes;
|
||||
if (!nodesGroupedByName.TryGetValue(nodeName, out nodes))
|
||||
{
|
||||
nodes = new List<XmlNode>();
|
||||
nodesGroupedByName.Add(nodeName, nodes);
|
||||
}
|
||||
|
||||
nodes.Add(childNode);
|
||||
}
|
||||
|
||||
// loop through grouped nodes. write single name instances as normal,
|
||||
// write multiple names together in an array
|
||||
foreach (KeyValuePair<string, List<XmlNode>> nodeNameGroup in nodesGroupedByName)
|
||||
{
|
||||
List<XmlNode> groupedNodes = nodeNameGroup.Value;
|
||||
|
||||
if (groupedNodes.Count == 1)
|
||||
{
|
||||
SerializeNode(writer, groupedNodes[0], true);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WritePropertyName(nodeNameGroup.Key);
|
||||
writer.WriteStartArray();
|
||||
|
||||
for (int i = 0; i < groupedNodes.Count; i++)
|
||||
{
|
||||
SerializeNode(writer, groupedNodes[i], false);
|
||||
}
|
||||
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SerializeNode(JsonWriter writer, XmlNode node, bool writePropertyName)
|
||||
{
|
||||
switch (node.NodeType)
|
||||
{
|
||||
case XmlNodeType.Document:
|
||||
case XmlNodeType.DocumentFragment:
|
||||
SerializeGroupedNodes(writer, node);
|
||||
break;
|
||||
case XmlNodeType.Element:
|
||||
if (writePropertyName)
|
||||
writer.WritePropertyName(node.Name);
|
||||
|
||||
if (CollectionUtils.IsNullOrEmpty(node.Attributes) && node.ChildNodes.Count == 1
|
||||
&& node.ChildNodes[0].NodeType == XmlNodeType.Text)
|
||||
{
|
||||
// write elements with a single text child as a name value pair
|
||||
writer.WriteValue(node.ChildNodes[0].Value);
|
||||
}
|
||||
else if (node.ChildNodes.Count == 0 && CollectionUtils.IsNullOrEmpty(node.Attributes))
|
||||
{
|
||||
// empty element
|
||||
writer.WriteNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
|
||||
for (int i = 0; i < node.Attributes.Count; i++)
|
||||
{
|
||||
SerializeNode(writer, node.Attributes[i], true);
|
||||
}
|
||||
|
||||
SerializeGroupedNodes(writer, node);
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
break;
|
||||
case XmlNodeType.Comment:
|
||||
if (writePropertyName)
|
||||
writer.WriteComment(node.Value);
|
||||
break;
|
||||
case XmlNodeType.Attribute:
|
||||
case XmlNodeType.Text:
|
||||
case XmlNodeType.CDATA:
|
||||
case XmlNodeType.ProcessingInstruction:
|
||||
case XmlNodeType.Whitespace:
|
||||
case XmlNodeType.SignificantWhitespace:
|
||||
if (writePropertyName)
|
||||
writer.WritePropertyName(GetPropertyName(node));
|
||||
writer.WriteValue(node.Value);
|
||||
break;
|
||||
case XmlNodeType.XmlDeclaration:
|
||||
XmlDeclaration declaration = (XmlDeclaration)node;
|
||||
writer.WritePropertyName(GetPropertyName(node));
|
||||
writer.WriteStartObject();
|
||||
|
||||
if (!string.IsNullOrEmpty(declaration.Version))
|
||||
{
|
||||
writer.WritePropertyName("@version");
|
||||
writer.WriteValue(declaration.Version);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(declaration.Encoding))
|
||||
{
|
||||
writer.WritePropertyName("@encoding");
|
||||
writer.WriteValue(declaration.Encoding);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(declaration.Standalone))
|
||||
{
|
||||
writer.WritePropertyName("@standalone");
|
||||
writer.WriteValue(declaration.Standalone);
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
break;
|
||||
default:
|
||||
throw new JsonSerializationException("Unexpected XmlNodeType when serializing nodes: " + node.NodeType);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Reading
|
||||
public override object ReadJson(JsonReader reader, Type objectType)
|
||||
{
|
||||
// maybe have CanReader and a CanWrite methods so this sort of test wouldn't be necessary
|
||||
if (objectType != typeof(XmlDocument))
|
||||
throw new JsonSerializationException("XmlNodeConverter only supports deserializing XmlDocuments");
|
||||
|
||||
XmlDocument document = new XmlDocument();
|
||||
XmlNamespaceManager manager = new XmlNamespaceManager(document.NameTable);
|
||||
reader.Read();
|
||||
|
||||
DeserializeNode(reader, document, manager, document);
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
private void DeserializeValue(JsonReader reader, XmlDocument document, XmlNamespaceManager manager, string propertyName, XmlNode currentNode)
|
||||
{
|
||||
switch (propertyName)
|
||||
{
|
||||
case TextName:
|
||||
currentNode.AppendChild(document.CreateTextNode(reader.Value.ToString()));
|
||||
break;
|
||||
case CDataName:
|
||||
currentNode.AppendChild(document.CreateCDataSection(reader.Value.ToString()));
|
||||
break;
|
||||
case WhitespaceName:
|
||||
currentNode.AppendChild(document.CreateWhitespace(reader.Value.ToString()));
|
||||
break;
|
||||
case SignificantWhitespaceName:
|
||||
currentNode.AppendChild(document.CreateSignificantWhitespace(reader.Value.ToString()));
|
||||
break;
|
||||
default:
|
||||
// processing instructions and the xml declaration start with ?
|
||||
if (propertyName[0] == '?')
|
||||
{
|
||||
if (propertyName == DeclarationName)
|
||||
{
|
||||
string version = null;
|
||||
string encoding = null;
|
||||
string standalone = null;
|
||||
while (reader.Read() && reader.TokenType != JsonToken.EndObject)
|
||||
{
|
||||
switch (reader.Value.ToString())
|
||||
{
|
||||
case "@version":
|
||||
reader.Read();
|
||||
version = reader.Value.ToString();
|
||||
break;
|
||||
case "@encoding":
|
||||
reader.Read();
|
||||
encoding = reader.Value.ToString();
|
||||
break;
|
||||
case "@standalone":
|
||||
reader.Read();
|
||||
standalone = reader.Value.ToString();
|
||||
break;
|
||||
default:
|
||||
throw new JsonSerializationException("Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
|
||||
}
|
||||
}
|
||||
|
||||
XmlDeclaration declaration = document.CreateXmlDeclaration(version, encoding, standalone);
|
||||
currentNode.AppendChild(declaration);
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlProcessingInstruction instruction = document.CreateProcessingInstruction(propertyName.Substring(1), reader.Value.ToString());
|
||||
currentNode.AppendChild(instruction);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// deserialize xml element
|
||||
bool finishedAttributes = false;
|
||||
bool finishedElement = false;
|
||||
string elementPrefix = GetPrefix(propertyName);
|
||||
Dictionary<string, string> attributeNameValues = new Dictionary<string, string>();
|
||||
|
||||
// a string token means the element only has a single text child
|
||||
if (reader.TokenType != JsonToken.String
|
||||
&& reader.TokenType != JsonToken.Null
|
||||
&& reader.TokenType != JsonToken.Boolean
|
||||
&& reader.TokenType != JsonToken.Integer
|
||||
&& reader.TokenType != JsonToken.Float
|
||||
&& reader.TokenType != JsonToken.Date)
|
||||
{
|
||||
// read properties until first non-attribute is encountered
|
||||
while (!finishedAttributes && !finishedElement && reader.Read())
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.PropertyName:
|
||||
string attributeName = reader.Value.ToString();
|
||||
|
||||
if (attributeName[0] == '@')
|
||||
{
|
||||
attributeName = attributeName.Substring(1);
|
||||
reader.Read();
|
||||
string attributeValue = reader.Value.ToString();
|
||||
attributeNameValues.Add(attributeName, attributeValue);
|
||||
|
||||
string namespacePrefix;
|
||||
|
||||
if (IsNamespaceAttribute(attributeName, out namespacePrefix))
|
||||
{
|
||||
manager.AddNamespace(namespacePrefix, attributeValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
finishedAttributes = true;
|
||||
}
|
||||
break;
|
||||
case JsonToken.EndObject:
|
||||
finishedElement = true;
|
||||
break;
|
||||
default:
|
||||
throw new JsonSerializationException("Unexpected JsonToken: " + reader.TokenType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// have to wait until attributes have been parsed before creating element
|
||||
// attributes may contain namespace info used by the element
|
||||
XmlElement element = (!string.IsNullOrEmpty(elementPrefix))
|
||||
? document.CreateElement(propertyName, manager.LookupNamespace(elementPrefix))
|
||||
: document.CreateElement(propertyName);
|
||||
|
||||
currentNode.AppendChild(element);
|
||||
|
||||
// add attributes to newly created element
|
||||
foreach (KeyValuePair<string, string> nameValue in attributeNameValues)
|
||||
{
|
||||
string attributePrefix = GetPrefix(nameValue.Key);
|
||||
|
||||
XmlAttribute attribute = (!string.IsNullOrEmpty(attributePrefix))
|
||||
? document.CreateAttribute(nameValue.Key, manager.LookupNamespace(attributePrefix))
|
||||
: document.CreateAttribute(nameValue.Key);
|
||||
|
||||
attribute.Value = nameValue.Value;
|
||||
|
||||
element.SetAttributeNode(attribute);
|
||||
}
|
||||
|
||||
if (reader.TokenType == JsonToken.String)
|
||||
{
|
||||
element.AppendChild(document.CreateTextNode(reader.Value.ToString()));
|
||||
}
|
||||
else if (reader.TokenType == JsonToken.Integer)
|
||||
{
|
||||
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((long)reader.Value)));
|
||||
}
|
||||
else if (reader.TokenType == JsonToken.Float)
|
||||
{
|
||||
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((double)reader.Value)));
|
||||
}
|
||||
else if (reader.TokenType == JsonToken.Boolean)
|
||||
{
|
||||
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((bool)reader.Value)));
|
||||
}
|
||||
else if (reader.TokenType == JsonToken.Date)
|
||||
{
|
||||
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((DateTime)reader.Value)));
|
||||
}
|
||||
else if (reader.TokenType == JsonToken.Null)
|
||||
{
|
||||
// empty element. do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
// finished element will have no children to deserialize
|
||||
if (!finishedElement)
|
||||
{
|
||||
manager.PushScope();
|
||||
|
||||
DeserializeNode(reader, document, manager, element);
|
||||
|
||||
manager.PopScope();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void DeserializeNode(JsonReader reader, XmlDocument document, XmlNamespaceManager manager, XmlNode currentNode)
|
||||
{
|
||||
do
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.PropertyName:
|
||||
string propertyName = reader.Value.ToString();
|
||||
reader.Read();
|
||||
|
||||
if (reader.TokenType == JsonToken.StartArray)
|
||||
{
|
||||
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
|
||||
{
|
||||
DeserializeValue(reader, document, manager, propertyName, currentNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DeserializeValue(reader, document, manager, propertyName, currentNode);
|
||||
}
|
||||
break;
|
||||
//case JsonToken.String:
|
||||
// DeserializeValue(reader, document, manager, TextName, currentNode);
|
||||
// break;
|
||||
case JsonToken.EndObject:
|
||||
case JsonToken.EndArray:
|
||||
return;
|
||||
default:
|
||||
throw new JsonSerializationException("Unexpected JsonToken when deserializing node: " + reader.TokenType);
|
||||
}
|
||||
} while (reader.TokenType == JsonToken.PropertyName || reader.Read());
|
||||
// don't read if current token is a property. token was already read when parsing element attributes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the attributeName is a namespace attribute.
|
||||
/// </summary>
|
||||
/// <param name="attributeName">Attribute name to test.</param>
|
||||
/// <param name="prefix">The attribute name prefix if it has one, otherwise an empty string.</param>
|
||||
/// <returns>True if attribute name is for a namespace attribute, otherwise false.</returns>
|
||||
private bool IsNamespaceAttribute(string attributeName, out string prefix)
|
||||
{
|
||||
if (attributeName.StartsWith("xmlns", StringComparison.Ordinal))
|
||||
{
|
||||
if (attributeName.Length == 5)
|
||||
{
|
||||
prefix = string.Empty;
|
||||
return true;
|
||||
}
|
||||
else if (attributeName[5] == ':')
|
||||
{
|
||||
prefix = attributeName.Substring(6, attributeName.Length - 6);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
prefix = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetPrefix(string qualifiedName)
|
||||
{
|
||||
int colonPosition = qualifiedName.IndexOf(':');
|
||||
|
||||
if ((colonPosition == -1 || colonPosition == 0) || (qualifiedName.Length - 1) == colonPosition)
|
||||
return string.Empty;
|
||||
else
|
||||
return qualifiedName.Substring(0, colonPosition);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override bool CanConvert(Type valueType)
|
||||
{
|
||||
return typeof(XmlNode).IsAssignableFrom(valueType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
public class Identifier
|
||||
{
|
||||
private string _name;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
}
|
||||
|
||||
public Identifier(string name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
private static bool IsAsciiLetter(char c)
|
||||
{
|
||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
Identifier function = obj as Identifier;
|
||||
|
||||
return Equals(function);
|
||||
}
|
||||
|
||||
public bool Equals(Identifier function)
|
||||
{
|
||||
return (_name == function.Name);
|
||||
}
|
||||
|
||||
public static bool Equals(Identifier a, Identifier b)
|
||||
{
|
||||
if (a == b)
|
||||
return true;
|
||||
|
||||
if (a != null && b != null)
|
||||
return a.Equals(b);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _name.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
public static bool operator ==(Identifier a, Identifier b)
|
||||
{
|
||||
return Identifier.Equals(a, b);
|
||||
}
|
||||
|
||||
public static bool operator !=(Identifier a, Identifier b)
|
||||
{
|
||||
return !Identifier.Equals(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a JavaScript array.
|
||||
/// </summary>
|
||||
public class JavaScriptArray : List<object>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JavaScriptObject"/> class.
|
||||
/// </summary>
|
||||
public JavaScriptArray()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JavaScriptArray"/> class that
|
||||
/// contains elements copied from the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="collection">The collection whose elements are copied to the new array.</param>
|
||||
public JavaScriptArray(IEnumerable<object> collection)
|
||||
: base(collection)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JavaScriptArray"/> class that
|
||||
/// is empty and has the specified initial capacity.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The number of elements that the new array can initially store.</param>
|
||||
public JavaScriptArray(int capacity)
|
||||
: base(capacity)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a JavaScript constructor.
|
||||
/// </summary>
|
||||
public class JavaScriptConstructor
|
||||
{
|
||||
private string _name;
|
||||
private JavaScriptParameters _parameters;
|
||||
|
||||
public JavaScriptParameters Parameters
|
||||
{
|
||||
get { return _parameters; }
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
}
|
||||
|
||||
public JavaScriptConstructor(string name, JavaScriptParameters parameters)
|
||||
{
|
||||
if (name == null)
|
||||
throw new ArgumentNullException("name");
|
||||
|
||||
if (name.Length == 0)
|
||||
throw new ArgumentException("Constructor name cannot be empty.", "name");
|
||||
|
||||
_name = name;
|
||||
_parameters = parameters ?? JavaScriptParameters.Empty;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.Append("new ");
|
||||
sb.Append(_name);
|
||||
sb.Append("(");
|
||||
if (_parameters != null)
|
||||
{
|
||||
for (int i = 0; i < _parameters.Count; i++)
|
||||
{
|
||||
sb.Append(_parameters[i]);
|
||||
}
|
||||
}
|
||||
sb.Append(")");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,448 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Globalization;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Reflection;
|
||||
using System.Data.SqlTypes;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
using System.Xml;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods for converting between common language runtime types and JavaScript types.
|
||||
/// </summary>
|
||||
public static class JavaScriptConvert
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents JavaScript's boolean value true as a string. This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly string True;
|
||||
|
||||
/// <summary>
|
||||
/// Represents JavaScript's boolean value false as a string. This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly string False;
|
||||
|
||||
/// <summary>
|
||||
/// Represents JavaScript's null as a string. This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly string Null;
|
||||
|
||||
/// <summary>
|
||||
/// Represents JavaScript's undefined as a string. This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly string Undefined;
|
||||
|
||||
internal static long InitialJavaScriptDateTicks;
|
||||
internal static DateTime MinimumJavaScriptDate;
|
||||
|
||||
static JavaScriptConvert()
|
||||
{
|
||||
True = "true";
|
||||
False = "false";
|
||||
Null = "null";
|
||||
Undefined = "undefined";
|
||||
|
||||
InitialJavaScriptDateTicks = (new DateTime(1970, 1, 1)).Ticks;
|
||||
MinimumJavaScriptDate = new DateTime(100, 1, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="DateTime"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="DateTime"/>.</returns>
|
||||
public static string ToString(DateTime value)
|
||||
{
|
||||
long javaScriptTicks = ConvertDateTimeToJavaScriptTicks(value);
|
||||
|
||||
return "new Date(" + javaScriptTicks + ")";
|
||||
}
|
||||
|
||||
internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime)
|
||||
{
|
||||
if (dateTime < MinimumJavaScriptDate)
|
||||
dateTime = MinimumJavaScriptDate;
|
||||
|
||||
long javaScriptTicks = (dateTime.Ticks - InitialJavaScriptDateTicks) / (long)10000;
|
||||
|
||||
return javaScriptTicks;
|
||||
}
|
||||
|
||||
internal static DateTime ConvertJavaScriptTicksToDateTime(long javaScriptTicks)
|
||||
{
|
||||
DateTime dateTime = new DateTime((javaScriptTicks * 10000) + InitialJavaScriptDateTicks);
|
||||
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Boolean"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="Boolean"/>.</returns>
|
||||
public static string ToString(bool value)
|
||||
{
|
||||
return (value) ? True : False;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Char"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="Char"/>.</returns>
|
||||
public static string ToString(char value)
|
||||
{
|
||||
return ToString(char.ToString(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Enum"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="Enum"/>.</returns>
|
||||
public static string ToString(Enum value)
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Int32"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="Int32"/>.</returns>
|
||||
public static string ToString(int value)
|
||||
{
|
||||
return value.ToString(null, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Int16"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="Int16"/>.</returns>
|
||||
public static string ToString(short value)
|
||||
{
|
||||
return value.ToString(null, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="UInt16"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="UInt16"/>.</returns>
|
||||
public static string ToString(ushort value)
|
||||
{
|
||||
return value.ToString(null, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="UInt32"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="UInt32"/>.</returns>
|
||||
public static string ToString(uint value)
|
||||
{
|
||||
return value.ToString(null, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Int64"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="Int64"/>.</returns>
|
||||
public static string ToString(long value)
|
||||
{
|
||||
return value.ToString(null, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="UInt64"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="UInt64"/>.</returns>
|
||||
public static string ToString(ulong value)
|
||||
{
|
||||
return value.ToString(null, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Single"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="Single"/>.</returns>
|
||||
public static string ToString(float value)
|
||||
{
|
||||
return value.ToString(null, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Double"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="Double"/>.</returns>
|
||||
public static string ToString(double value)
|
||||
{
|
||||
return value.ToString(null, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Byte"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="Byte"/>.</returns>
|
||||
public static string ToString(byte value)
|
||||
{
|
||||
return value.ToString(null, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="SByte"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="SByte"/>.</returns>
|
||||
public static string ToString(sbyte value)
|
||||
{
|
||||
return value.ToString(null, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Decimal"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="SByte"/>.</returns>
|
||||
public static string ToString(decimal value)
|
||||
{
|
||||
return value.ToString(null, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Guid"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="Guid"/>.</returns>
|
||||
public static string ToString(Guid value)
|
||||
{
|
||||
return '"' + value.ToString("D", CultureInfo.InvariantCulture) + '"';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="String"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="String"/>.</returns>
|
||||
public static string ToString(string value)
|
||||
{
|
||||
return ToString(value, '"');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="String"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <param name="delimter">The string delimiter character.</param>
|
||||
/// <returns>A Json string representation of the <see cref="String"/>.</returns>
|
||||
public static string ToString(string value, char delimter)
|
||||
{
|
||||
return JavaScriptUtils.ToEscapedJavaScriptString(value, delimter, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="Object"/> to it's JavaScript string representation.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert.</param>
|
||||
/// <returns>A Json string representation of the <see cref="Object"/>.</returns>
|
||||
public static string ToString(object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return Null;
|
||||
}
|
||||
else if (value is IConvertible)
|
||||
{
|
||||
IConvertible convertible = value as IConvertible;
|
||||
|
||||
switch (convertible.GetTypeCode())
|
||||
{
|
||||
case TypeCode.String:
|
||||
return ToString((string)convertible);
|
||||
case TypeCode.Char:
|
||||
return ToString((char)convertible);
|
||||
case TypeCode.Boolean:
|
||||
return ToString((bool)convertible);
|
||||
case TypeCode.SByte:
|
||||
return ToString((sbyte)convertible);
|
||||
case TypeCode.Int16:
|
||||
return ToString((short)convertible);
|
||||
case TypeCode.UInt16:
|
||||
return ToString((ushort)convertible);
|
||||
case TypeCode.Int32:
|
||||
return ToString((int)convertible);
|
||||
case TypeCode.Byte:
|
||||
return ToString((byte)convertible);
|
||||
case TypeCode.UInt32:
|
||||
return ToString((uint)convertible);
|
||||
case TypeCode.Int64:
|
||||
return ToString((long)convertible);
|
||||
case TypeCode.UInt64:
|
||||
return ToString((ulong)convertible);
|
||||
case TypeCode.Single:
|
||||
return ToString((float)convertible);
|
||||
case TypeCode.Double:
|
||||
return ToString((double)convertible);
|
||||
case TypeCode.DateTime:
|
||||
return ToString((DateTime)convertible);
|
||||
case TypeCode.Decimal:
|
||||
return ToString((decimal)convertible);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException(string.Format("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.", value.GetType()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the specified object to a Json object.
|
||||
/// </summary>
|
||||
/// <param name="value">The object to serialize.</param>
|
||||
/// <returns>A Json string representation of the object.</returns>
|
||||
public static string SerializeObject(object value)
|
||||
{
|
||||
return SerializeObject(value, null);
|
||||
}
|
||||
|
||||
public static string SerializeObject(object value, params JsonConverter[] converters)
|
||||
{
|
||||
StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
|
||||
JsonSerializer jsonSerializer = new JsonSerializer();
|
||||
|
||||
if (!CollectionUtils.IsNullOrEmpty<JsonConverter>(converters))
|
||||
{
|
||||
for (int i = 0; i < converters.Length; i++)
|
||||
{
|
||||
jsonSerializer.Converters.Add(converters[i]);
|
||||
}
|
||||
}
|
||||
|
||||
using (JsonWriter jsonWriter = new JsonWriter(sw))
|
||||
{
|
||||
//jsonWriter.Formatting = Formatting.Indented;
|
||||
jsonSerializer.Serialize(jsonWriter, value);
|
||||
}
|
||||
|
||||
return sw.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the specified object to a Json object.
|
||||
/// </summary>
|
||||
/// <param name="value">The object to deserialize.</param>
|
||||
/// <returns>The deserialized object from the Json string.</returns>
|
||||
public static object DeserializeObject(string value)
|
||||
{
|
||||
return DeserializeObject(value, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the specified object to a Json object.
|
||||
/// </summary>
|
||||
/// <param name="value">The object to deserialize.</param>
|
||||
/// <param name="type">The <see cref="Type"/> of object being deserialized.</param>
|
||||
/// <returns>The deserialized object from the Json string.</returns>
|
||||
public static object DeserializeObject(string value, Type type)
|
||||
{
|
||||
return DeserializeObject(value, type, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the specified object to a Json object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the object to deserialize.</typeparam>
|
||||
/// <param name="value">The object to deserialize.</param>
|
||||
/// <returns>The deserialized object from the Json string.</returns>
|
||||
public static T DeserializeObject<T>(string value)
|
||||
{
|
||||
return DeserializeObject<T>(value, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the specified object to a Json object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the object to deserialize.</typeparam>
|
||||
/// <param name="value">The object to deserialize.</param>
|
||||
/// <param name="converters">Converters to use while deserializing.</param>
|
||||
/// <returns>The deserialized object from the Json string.</returns>
|
||||
public static T DeserializeObject<T>(string value, params JsonConverter[] converters)
|
||||
{
|
||||
return (T)DeserializeObject(value, typeof(T), converters);
|
||||
}
|
||||
|
||||
public static object DeserializeObject(string value, Type type, params JsonConverter[] converters)
|
||||
{
|
||||
StringReader sr = new StringReader(value);
|
||||
JsonSerializer jsonSerializer = new JsonSerializer();
|
||||
|
||||
if (!CollectionUtils.IsNullOrEmpty<JsonConverter>(converters))
|
||||
{
|
||||
for (int i = 0; i < converters.Length; i++)
|
||||
{
|
||||
jsonSerializer.Converters.Add(converters[i]);
|
||||
}
|
||||
}
|
||||
|
||||
object deserializedValue;
|
||||
|
||||
using (JsonReader jsonReader = new JsonReader(sr))
|
||||
{
|
||||
deserializedValue = jsonSerializer.Deserialize(jsonReader, type);
|
||||
}
|
||||
|
||||
return deserializedValue;
|
||||
}
|
||||
|
||||
public static string SerializeXmlNode(XmlNode node)
|
||||
{
|
||||
XmlNodeConverter converter = new XmlNodeConverter();
|
||||
|
||||
return SerializeObject(node, converter);
|
||||
}
|
||||
|
||||
public static XmlNode DeerializeXmlNode(string value)
|
||||
{
|
||||
XmlNodeConverter converter = new XmlNodeConverter();
|
||||
|
||||
return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), converter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a JavaScript object.
|
||||
/// </summary>
|
||||
public class JavaScriptObject : Dictionary<string, object>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JavaScriptObject"/> class.
|
||||
/// </summary>
|
||||
public JavaScriptObject()
|
||||
: base(EqualityComparer<string>.Default)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JavaScriptObject"/> class that
|
||||
/// contains values copied from the specified <see cref="JavaScriptObject"/>.
|
||||
/// </summary>
|
||||
/// <param name="javaScriptObject">The <see cref="JavaScriptObject"/> whose elements are copied to the new object.</param>
|
||||
public JavaScriptObject(JavaScriptObject javaScriptObject)
|
||||
: base(javaScriptObject, EqualityComparer<string>.Default)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
public class JavaScriptParameters : ReadOnlyCollection<object>
|
||||
{
|
||||
public static readonly JavaScriptParameters Empty = new JavaScriptParameters(new List<object>());
|
||||
|
||||
public JavaScriptParameters(IList<object> list)
|
||||
: base(list)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
public abstract class JsonConverter
|
||||
{
|
||||
public virtual void WriteJson(JsonWriter writer, object value)
|
||||
{
|
||||
JsonSerializer serializer = new JsonSerializer();
|
||||
|
||||
serializer.Serialize(writer, value);
|
||||
}
|
||||
|
||||
public virtual object ReadJson(JsonReader reader, Type objectType)
|
||||
{
|
||||
throw new NotImplementedException(string.Format("{0} has not overriden FromJson method.", GetType().Name));
|
||||
}
|
||||
|
||||
public abstract bool CanConvert(Type objectType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
public class JsonConverterCollection : Collection<JsonConverter>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
using System.Xml;
|
||||
using System.Text;
|
||||
using System.Security.Principal;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
public abstract class JsonHandler : HandlerBase, IHttpHandler
|
||||
{
|
||||
public event EventHandler Error;
|
||||
|
||||
protected abstract void WriteResult(JsonWriter writer);
|
||||
|
||||
public static void JsonResponse(HttpResponse response, Action<JsonWriter> writeAction)
|
||||
{
|
||||
response.ClearHeaders();
|
||||
response.ClearContent();
|
||||
|
||||
JsonWriter writer = new JsonWriter(response.Output);
|
||||
|
||||
writeAction(writer);
|
||||
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
protected virtual void OnError(EventArgs e)
|
||||
{
|
||||
if (Error != null)
|
||||
{
|
||||
Error(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
void IHttpHandler.ProcessRequest(HttpContext context)
|
||||
{
|
||||
if (context == null)
|
||||
throw new ArgumentNullException("context");
|
||||
|
||||
Context = context;
|
||||
|
||||
try
|
||||
{
|
||||
JsonHandler.JsonResponse(context.Response, new Action<JsonWriter>(WriteResult));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
context.AddError(exception);
|
||||
OnError(EventArgs.Empty);
|
||||
if (context.Error != null)
|
||||
{
|
||||
throw new HttpUnhandledException("blah", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IHttpHandler.IsReusable
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
|
||||
public sealed class JsonIgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
|
||||
public sealed class JsonPropertyAttribute : Attribute
|
||||
{
|
||||
private string _propertyName;
|
||||
|
||||
public string PropertyName
|
||||
{
|
||||
get { return _propertyName; }
|
||||
set { _propertyName = value; }
|
||||
}
|
||||
|
||||
public JsonPropertyAttribute(string propertyName)
|
||||
{
|
||||
_propertyName = propertyName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,897 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
|
||||
/// </summary>
|
||||
public class JsonReader : IDisposable
|
||||
{
|
||||
private enum State
|
||||
{
|
||||
Start,
|
||||
Complete,
|
||||
Property,
|
||||
ObjectStart,
|
||||
Object,
|
||||
ArrayStart,
|
||||
Array,
|
||||
Closed,
|
||||
PostValue,
|
||||
Constructor,
|
||||
ConstructorEnd,
|
||||
Error,
|
||||
Finished
|
||||
}
|
||||
|
||||
private TextReader _reader;
|
||||
private char _currentChar;
|
||||
|
||||
// current Token data
|
||||
private JsonToken _token;
|
||||
private object _value;
|
||||
private Type _valueType;
|
||||
private char _quoteChar;
|
||||
private StringBuffer _buffer;
|
||||
//private StringBuilder _testBuffer;
|
||||
private State _currentState;
|
||||
|
||||
private int _top;
|
||||
private List<JsonType> _stack;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the quotation mark character used to enclose the value of a string.
|
||||
/// </summary>
|
||||
public char QuoteChar
|
||||
{
|
||||
get { return _quoteChar; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the current Json token.
|
||||
/// </summary>
|
||||
public JsonToken TokenType
|
||||
{
|
||||
get { return _token; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the text value of the current Json token.
|
||||
/// </summary>
|
||||
public object Value
|
||||
{
|
||||
get { return _value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets The Common Language Runtime (CLR) type for the current Json token.
|
||||
/// </summary>
|
||||
public Type ValueType
|
||||
{
|
||||
get { return _valueType; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonReader"/> class with the specified <see cref="TextReader"/>.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <c>TextReader</c> containing the XML data to read.</param>
|
||||
public JsonReader(TextReader reader)
|
||||
{
|
||||
if (reader == null)
|
||||
throw new ArgumentNullException("reader");
|
||||
|
||||
_reader = reader;
|
||||
_buffer = new StringBuffer(4096);
|
||||
//_testBuffer = new StringBuilder();
|
||||
_currentState = State.Start;
|
||||
_stack = new List<JsonType>();
|
||||
_top = 0;
|
||||
Push(JsonType.None);
|
||||
}
|
||||
|
||||
private void Push(JsonType value)
|
||||
{
|
||||
_stack.Add(value);
|
||||
_top++;
|
||||
}
|
||||
|
||||
private JsonType Pop()
|
||||
{
|
||||
JsonType value = Peek();
|
||||
_stack.RemoveAt(_stack.Count - 1);
|
||||
_top--;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private JsonType Peek()
|
||||
{
|
||||
return _stack[_top - 1];
|
||||
}
|
||||
|
||||
private void ParseString(char quote)
|
||||
{
|
||||
bool stringTerminated = false;
|
||||
|
||||
while (!stringTerminated && MoveNext())
|
||||
{
|
||||
switch (_currentChar)
|
||||
{
|
||||
//case 0:
|
||||
//case 0x0A:
|
||||
//case 0x0D:
|
||||
// throw new JsonReaderException("Unterminated string");
|
||||
case '\\':
|
||||
if (MoveNext())
|
||||
{
|
||||
switch (_currentChar)
|
||||
{
|
||||
case 'b':
|
||||
_buffer.Append('\b');
|
||||
break;
|
||||
case 't':
|
||||
_buffer.Append('\t');
|
||||
break;
|
||||
case 'n':
|
||||
_buffer.Append('\n');
|
||||
break;
|
||||
case 'f':
|
||||
_buffer.Append('\f');
|
||||
break;
|
||||
case 'r':
|
||||
_buffer.Append('\r');
|
||||
break;
|
||||
case 'u':
|
||||
//_buffer.Append((char) Integer.parseInt(next(4), 16));
|
||||
break;
|
||||
case 'x':
|
||||
//_buffer.Append((char) Integer.parseInt(next(2), 16));
|
||||
break;
|
||||
default:
|
||||
_buffer.Append(_currentChar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("Unterminated string. Expected delimiter: " + quote);
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
case '\'':
|
||||
if (_currentChar == quote)
|
||||
stringTerminated = true;
|
||||
else
|
||||
goto default;
|
||||
break;
|
||||
default:
|
||||
_buffer.Append(_currentChar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stringTerminated)
|
||||
throw new JsonReaderException("Unterminated string. Expected delimiter: " + quote);
|
||||
|
||||
ClearCurrentChar();
|
||||
_currentState = State.PostValue;
|
||||
_token = JsonToken.String;
|
||||
_value = _buffer.ToString();
|
||||
_buffer.Position = 0;
|
||||
_valueType = typeof(string);
|
||||
_quoteChar = quote;
|
||||
}
|
||||
|
||||
private bool MoveNext()
|
||||
{
|
||||
int value = _reader.Read();
|
||||
|
||||
if (value != -1)
|
||||
{
|
||||
_currentChar = (char)value;
|
||||
//_testBuffer.Append(_currentChar);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasNext()
|
||||
{
|
||||
return (_reader.Peek() != -1);
|
||||
}
|
||||
|
||||
private char PeekNext()
|
||||
{
|
||||
return (char)_reader.Peek();
|
||||
}
|
||||
|
||||
private void ClearCurrentChar()
|
||||
{
|
||||
_currentChar = '\0';
|
||||
}
|
||||
|
||||
private bool MoveTo(char value)
|
||||
{
|
||||
while (MoveNext())
|
||||
{
|
||||
if (_currentChar == value)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next Json token from the stream.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Read()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (_currentChar == '\0')
|
||||
{
|
||||
if (!MoveNext())
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (_currentState)
|
||||
{
|
||||
case State.Start:
|
||||
case State.Property:
|
||||
case State.Array:
|
||||
case State.ArrayStart:
|
||||
return ParseValue();
|
||||
case State.Complete:
|
||||
break;
|
||||
case State.Object:
|
||||
case State.ObjectStart:
|
||||
return ParseObject();
|
||||
case State.PostValue:
|
||||
// returns true if it hits
|
||||
// end of object or array
|
||||
if (ParsePostValue())
|
||||
return true;
|
||||
break;
|
||||
case State.Closed:
|
||||
break;
|
||||
case State.Error:
|
||||
break;
|
||||
default:
|
||||
throw new JsonReaderException("Unexpected state: " + _currentState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ParsePostValue()
|
||||
{
|
||||
do
|
||||
{
|
||||
switch (_currentChar)
|
||||
{
|
||||
case '}':
|
||||
SetToken(JsonToken.EndObject);
|
||||
ClearCurrentChar();
|
||||
return true;
|
||||
case ']':
|
||||
SetToken(JsonToken.EndArray);
|
||||
ClearCurrentChar();
|
||||
return true;
|
||||
case '/':
|
||||
ParseComment();
|
||||
return true;
|
||||
case ',':
|
||||
// finished paring
|
||||
SetStateBasedOnCurrent();
|
||||
ClearCurrentChar();
|
||||
return false;
|
||||
default:
|
||||
if (char.IsWhiteSpace(_currentChar))
|
||||
{
|
||||
// eat whitespace
|
||||
ClearCurrentChar();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("After parsing a value an unexpected character was encoutered: " + _currentChar);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (MoveNext());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool ParseObject()
|
||||
{
|
||||
do
|
||||
{
|
||||
switch (_currentChar)
|
||||
{
|
||||
case '}':
|
||||
SetToken(JsonToken.EndObject);
|
||||
return true;
|
||||
case '/':
|
||||
ParseComment();
|
||||
return true;
|
||||
case ',':
|
||||
SetToken(JsonToken.Undefined);
|
||||
return true;
|
||||
default:
|
||||
if (char.IsWhiteSpace(_currentChar))
|
||||
{
|
||||
// eat
|
||||
}
|
||||
else
|
||||
{
|
||||
return ParseProperty();
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (MoveNext());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool ParseProperty()
|
||||
{
|
||||
if (ValidIdentifierChar(_currentChar))
|
||||
{
|
||||
ParseUnquotedProperty();
|
||||
}
|
||||
else if (_currentChar == '"' || _currentChar == '\'')
|
||||
{
|
||||
ParseQuotedProperty(_currentChar);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("Invalid property identifier character: " + _currentChar);
|
||||
}
|
||||
|
||||
// finished property. move to colon
|
||||
if (_currentChar != ':')
|
||||
{
|
||||
MoveTo(':');
|
||||
}
|
||||
|
||||
SetToken(JsonToken.PropertyName, _buffer.ToString());
|
||||
_buffer.Position = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ParseQuotedProperty(char quoteChar)
|
||||
{
|
||||
// parse property name until quoted char is hit
|
||||
while (MoveNext())
|
||||
{
|
||||
if (_currentChar == quoteChar)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
_buffer.Append(_currentChar);
|
||||
}
|
||||
}
|
||||
|
||||
throw new JsonReaderException("Unclosed quoted property. Expected: " + quoteChar);
|
||||
}
|
||||
|
||||
private bool ValidIdentifierChar(char value)
|
||||
{
|
||||
return (char.IsLetterOrDigit(_currentChar) || _currentChar == '_' || _currentChar == '$');
|
||||
}
|
||||
|
||||
private void ParseUnquotedProperty()
|
||||
{
|
||||
// parse unquoted property name until whitespace or colon
|
||||
_buffer.Append(_currentChar);
|
||||
|
||||
while (MoveNext())
|
||||
{
|
||||
if (char.IsWhiteSpace(_currentChar) || _currentChar == ':')
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (ValidIdentifierChar(_currentChar))
|
||||
{
|
||||
_buffer.Append(_currentChar);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("Invalid JavaScript property identifier character: " + _currentChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetToken(JsonToken newToken)
|
||||
{
|
||||
SetToken(newToken, null);
|
||||
}
|
||||
|
||||
private void SetToken(JsonToken newToken, object value)
|
||||
{
|
||||
_token = newToken;
|
||||
|
||||
switch (newToken)
|
||||
{
|
||||
case JsonToken.StartObject:
|
||||
_currentState = State.ObjectStart;
|
||||
Push(JsonType.Object);
|
||||
ClearCurrentChar();
|
||||
break;
|
||||
case JsonToken.StartArray:
|
||||
_currentState = State.ArrayStart;
|
||||
Push(JsonType.Array);
|
||||
ClearCurrentChar();
|
||||
break;
|
||||
case JsonToken.EndObject:
|
||||
ValidateEnd(JsonToken.EndObject);
|
||||
ClearCurrentChar();
|
||||
_currentState = State.PostValue;
|
||||
break;
|
||||
case JsonToken.EndArray:
|
||||
ValidateEnd(JsonToken.EndArray);
|
||||
ClearCurrentChar();
|
||||
_currentState = State.PostValue;
|
||||
break;
|
||||
case JsonToken.PropertyName:
|
||||
_currentState = State.Property;
|
||||
ClearCurrentChar();
|
||||
break;
|
||||
case JsonToken.Undefined:
|
||||
case JsonToken.Integer:
|
||||
case JsonToken.Float:
|
||||
case JsonToken.Boolean:
|
||||
case JsonToken.Null:
|
||||
case JsonToken.Constructor:
|
||||
case JsonToken.Date:
|
||||
_currentState = State.PostValue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
_value = value;
|
||||
_valueType = value.GetType();
|
||||
}
|
||||
else
|
||||
{
|
||||
_value = null;
|
||||
_valueType = null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ParseValue()
|
||||
{
|
||||
do
|
||||
{
|
||||
switch (_currentChar)
|
||||
{
|
||||
case '"':
|
||||
case '\'':
|
||||
ParseString(_currentChar);
|
||||
return true;
|
||||
case 't':
|
||||
ParseTrue();
|
||||
return true;
|
||||
case 'f':
|
||||
ParseFalse();
|
||||
return true;
|
||||
case 'n':
|
||||
if (HasNext())
|
||||
{
|
||||
char next = PeekNext();
|
||||
|
||||
if (next == 'u')
|
||||
ParseNull();
|
||||
else if (next == 'e')
|
||||
ParseConstructor();
|
||||
else
|
||||
throw new JsonReaderException("Unexpected character encountered while parsing value: " + _currentChar);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("Unexpected end");
|
||||
}
|
||||
return true;
|
||||
case '/':
|
||||
ParseComment();
|
||||
return true;
|
||||
case 'u':
|
||||
ParseUndefined();
|
||||
return true;
|
||||
case '{':
|
||||
SetToken(JsonToken.StartObject);
|
||||
return true;
|
||||
case '[':
|
||||
SetToken(JsonToken.StartArray);
|
||||
return true;
|
||||
case '}':
|
||||
SetToken(JsonToken.EndObject);
|
||||
return true;
|
||||
case ']':
|
||||
SetToken(JsonToken.EndArray);
|
||||
return true;
|
||||
case ',':
|
||||
SetToken(JsonToken.Undefined);
|
||||
//ClearCurrentChar();
|
||||
return true;
|
||||
case ')':
|
||||
if (_currentState == State.Constructor)
|
||||
{
|
||||
_currentState = State.ConstructorEnd;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("Unexpected character encountered while parsing value: " + _currentChar);
|
||||
}
|
||||
default:
|
||||
if (char.IsWhiteSpace(_currentChar))
|
||||
{
|
||||
// eat
|
||||
}
|
||||
else if (char.IsNumber(_currentChar) || _currentChar == '-' || _currentChar == '.')
|
||||
{
|
||||
ParseNumber();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("Unexpected character encountered while parsing value: " + _currentChar);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (MoveNext());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool EatWhitespace(bool oneOrMore)
|
||||
{
|
||||
bool whitespace = false;
|
||||
while (char.IsWhiteSpace(_currentChar))
|
||||
{
|
||||
whitespace = true;
|
||||
MoveNext();
|
||||
}
|
||||
|
||||
return (!oneOrMore || whitespace);
|
||||
}
|
||||
|
||||
private void ParseConstructor()
|
||||
{
|
||||
if (MatchValue("new", true))
|
||||
{
|
||||
if (EatWhitespace(true))
|
||||
{
|
||||
while (char.IsLetter(_currentChar))
|
||||
{
|
||||
_buffer.Append(_currentChar);
|
||||
MoveNext();
|
||||
}
|
||||
|
||||
string constructorName = _buffer.ToString();
|
||||
_buffer.Position = 0;
|
||||
|
||||
List<object> parameters = new List<object>();
|
||||
|
||||
EatWhitespace(false);
|
||||
|
||||
if (_currentChar == '(' && MoveNext())
|
||||
{
|
||||
_currentState = State.Constructor;
|
||||
|
||||
while (ParseValue())
|
||||
{
|
||||
parameters.Add(_value);
|
||||
_currentState = State.Constructor;
|
||||
}
|
||||
|
||||
if (string.CompareOrdinal(constructorName, "Date") == 0)
|
||||
{
|
||||
long javaScriptTicks = Convert.ToInt64(parameters[0]);
|
||||
|
||||
DateTime date = JavaScriptConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
|
||||
|
||||
SetToken(JsonToken.Date, date);
|
||||
}
|
||||
else
|
||||
{
|
||||
JavaScriptConstructor constructor = new JavaScriptConstructor(constructorName, new JavaScriptParameters(parameters));
|
||||
|
||||
if (_currentState == State.ConstructorEnd)
|
||||
{
|
||||
SetToken(JsonToken.Constructor, constructor);
|
||||
}
|
||||
}
|
||||
|
||||
// move past ')'
|
||||
MoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseNumber()
|
||||
{
|
||||
// parse until seperator character or end
|
||||
bool end = false;
|
||||
do
|
||||
{
|
||||
if (CurrentIsSeperator())
|
||||
end = true;
|
||||
else
|
||||
_buffer.Append(_currentChar);
|
||||
|
||||
} while (!end && MoveNext());
|
||||
|
||||
string number = _buffer.ToString();
|
||||
object numberValue;
|
||||
JsonToken numberType;
|
||||
|
||||
if (number.IndexOf('.') == -1)
|
||||
{
|
||||
numberValue = Convert.ToInt64(_buffer.ToString(), CultureInfo.InvariantCulture);
|
||||
numberType = JsonToken.Integer;
|
||||
}
|
||||
else
|
||||
{
|
||||
numberValue = Convert.ToDouble(_buffer.ToString(), CultureInfo.InvariantCulture);
|
||||
numberType = JsonToken.Float;
|
||||
}
|
||||
|
||||
_buffer.Position = 0;
|
||||
|
||||
SetToken(numberType, numberValue);
|
||||
}
|
||||
|
||||
private void ValidateEnd(JsonToken endToken)
|
||||
{
|
||||
JsonType currentObject = Pop();
|
||||
|
||||
if (GetTypeForCloseToken(endToken) != currentObject)
|
||||
throw new JsonReaderException(string.Format("JsonToken {0} is not valid for closing JsonType {1}.", endToken, currentObject));
|
||||
}
|
||||
|
||||
private void SetStateBasedOnCurrent()
|
||||
{
|
||||
JsonType currentObject = Peek();
|
||||
|
||||
switch (currentObject)
|
||||
{
|
||||
case JsonType.Object:
|
||||
_currentState = State.Object;
|
||||
break;
|
||||
case JsonType.Array:
|
||||
_currentState = State.Array;
|
||||
break;
|
||||
case JsonType.None:
|
||||
_currentState = State.Finished;
|
||||
break;
|
||||
default:
|
||||
throw new JsonReaderException("While setting the reader state back to current object an unexpected JsonType was encountered: " + currentObject);
|
||||
}
|
||||
}
|
||||
|
||||
private JsonType GetTypeForCloseToken(JsonToken token)
|
||||
{
|
||||
switch (token)
|
||||
{
|
||||
case JsonToken.EndObject:
|
||||
return JsonType.Object;
|
||||
case JsonToken.EndArray:
|
||||
return JsonType.Array;
|
||||
default:
|
||||
throw new JsonReaderException("Not a valid close JsonToken: " + token);
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseComment()
|
||||
{
|
||||
// should have already parsed / character before reaching this method
|
||||
|
||||
MoveNext();
|
||||
|
||||
if (_currentChar == '*')
|
||||
{
|
||||
while (MoveNext())
|
||||
{
|
||||
if (_currentChar == '*')
|
||||
{
|
||||
if (MoveNext())
|
||||
{
|
||||
if (_currentChar == '/')
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
_buffer.Append('*');
|
||||
_buffer.Append(_currentChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_buffer.Append(_currentChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("Error parsing comment. Expected: *");
|
||||
}
|
||||
|
||||
SetToken(JsonToken.Comment, _buffer.ToString());
|
||||
|
||||
_buffer.Position = 0;
|
||||
|
||||
ClearCurrentChar();
|
||||
}
|
||||
|
||||
private bool MatchValue(string value)
|
||||
{
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
if (_currentChar != value[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
while (i < value.Length && MoveNext());
|
||||
|
||||
return (i == value.Length);
|
||||
}
|
||||
|
||||
private bool MatchValue(string value, bool noTrailingNonSeperatorCharacters)
|
||||
{
|
||||
// will match value and then move to the next character, checking that it is a seperator character
|
||||
bool match = MatchValue(value);
|
||||
|
||||
if (!noTrailingNonSeperatorCharacters)
|
||||
return match;
|
||||
else
|
||||
return (match && (!MoveNext() || CurrentIsSeperator()));
|
||||
}
|
||||
|
||||
private bool CurrentIsSeperator()
|
||||
{
|
||||
switch (_currentChar)
|
||||
{
|
||||
case '}':
|
||||
case ']':
|
||||
case ',':
|
||||
return true;
|
||||
case '/':
|
||||
// check next character to see if start of a comment
|
||||
return (HasNext() && PeekNext() == '*');
|
||||
case ')':
|
||||
if (_currentState == State.Constructor)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
if (char.IsWhiteSpace(_currentChar))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ParseTrue()
|
||||
{
|
||||
// check characters equal 'true'
|
||||
// and that it is followed by either a seperator character
|
||||
// or the text ends
|
||||
if (MatchValue(JavaScriptConvert.True, true))
|
||||
{
|
||||
SetToken(JsonToken.Boolean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("Error parsing boolean value.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseNull()
|
||||
{
|
||||
if (MatchValue(JavaScriptConvert.Null, true))
|
||||
{
|
||||
SetToken(JsonToken.Null);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("Error parsing null value.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseUndefined()
|
||||
{
|
||||
if (MatchValue(JavaScriptConvert.Undefined, true))
|
||||
{
|
||||
SetToken(JsonToken.Undefined);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("Error parsing undefined value.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseFalse()
|
||||
{
|
||||
if (MatchValue(JavaScriptConvert.False, true))
|
||||
{
|
||||
SetToken(JsonToken.Boolean, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonReaderException("Error parsing boolean value.");
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (_currentState != State.Closed && disposing)
|
||||
Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the <see cref="State"/> to Closed.
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
_currentState = State.Closed;
|
||||
_token = JsonToken.None;
|
||||
_value = null;
|
||||
_valueType = null;
|
||||
|
||||
if (_reader != null)
|
||||
_reader.Close();
|
||||
|
||||
if (_buffer != null)
|
||||
_buffer.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception thrown when an error occurs while reading Json text.
|
||||
/// </summary>
|
||||
public class JsonReaderException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonReaderException"/> class.
|
||||
/// </summary>
|
||||
public JsonReaderException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonReaderException"/> class
|
||||
/// with a specified error message.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
public JsonReaderException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonReaderException"/> class
|
||||
/// with a specified error message and a reference to the inner exception that is the cause of this exception.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
|
||||
public JsonReaderException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception thrown when an error occurs during Json serialization or deserialization.
|
||||
/// </summary>
|
||||
public class JsonSerializationException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonSerializationException"/> class.
|
||||
/// </summary>
|
||||
public JsonSerializationException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonSerializationException"/> class
|
||||
/// with a specified error message.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
public JsonSerializationException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonSerializationException"/> class
|
||||
/// with a specified error message and a reference to the inner exception that is the cause of this exception.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
|
||||
public JsonSerializationException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,649 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.ComponentModel;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies reference loop handling options for the <see cref="JsonWriter"/>.
|
||||
/// </summary>
|
||||
public enum ReferenceLoopHandling
|
||||
{
|
||||
/// <summary>
|
||||
/// Throw a <see cref="JsonSerializationException"/> when a loop is encountered.
|
||||
/// </summary>
|
||||
Error = 0,
|
||||
/// <summary>
|
||||
/// Ignore loop references and do not serialize.
|
||||
/// </summary>
|
||||
Ignore = 1,
|
||||
/// <summary>
|
||||
/// Serialize loop references.
|
||||
/// </summary>
|
||||
Serialize = 2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes and deserializes objects into and from the Json format.
|
||||
/// The <see cref="JsonSerializer"/> enables you to control how objects are encoded into Json.
|
||||
/// </summary>
|
||||
public class JsonSerializer
|
||||
{
|
||||
private ReferenceLoopHandling _referenceLoopHandling;
|
||||
private int _level;
|
||||
private JsonConverterCollection _converters;
|
||||
private Dictionary<Type, MemberMappingCollection> _typeMemberMappings;
|
||||
|
||||
/// <summary>
|
||||
/// Get or set how reference loops (e.g. a class referencing itself) is handled.
|
||||
/// </summary>
|
||||
public ReferenceLoopHandling ReferenceLoopHandling
|
||||
{
|
||||
get { return _referenceLoopHandling; }
|
||||
set
|
||||
{
|
||||
if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("value");
|
||||
}
|
||||
_referenceLoopHandling = value;
|
||||
}
|
||||
}
|
||||
|
||||
public JsonConverterCollection Converters
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_converters == null)
|
||||
_converters = new JsonConverterCollection();
|
||||
|
||||
return _converters;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonSerializer"/> class.
|
||||
/// </summary>
|
||||
public JsonSerializer()
|
||||
{
|
||||
_referenceLoopHandling = ReferenceLoopHandling.Error;
|
||||
}
|
||||
|
||||
#region Deserialize
|
||||
/// <summary>
|
||||
/// Deserializes the Json structure contained by the specified <see cref="JsonReader"/>.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="JsonReader"/> that contains the Json structure to deserialize.</param>
|
||||
/// <returns>The <see cref="Object"/> being deserialized.</returns>
|
||||
public object Deserialize(JsonReader reader)
|
||||
{
|
||||
return Deserialize(reader, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the Json structure contained by the specified <see cref="JsonReader"/>
|
||||
/// into an instance of the specified type.
|
||||
/// </summary>
|
||||
/// <param name="reader">The type of object to create.</param>
|
||||
/// <param name="objectType">The <see cref="Type"/> of object being deserialized.</param>
|
||||
/// <returns>The instance of <paramref name="objectType"/> being deserialized.</returns>
|
||||
public object Deserialize(JsonReader reader, Type objectType)
|
||||
{
|
||||
if (reader == null)
|
||||
throw new ArgumentNullException("reader");
|
||||
|
||||
if (!reader.Read())
|
||||
return null;
|
||||
|
||||
return GetObject(reader, objectType);
|
||||
}
|
||||
|
||||
private JavaScriptArray PopulateJavaScriptArray(JsonReader reader)
|
||||
{
|
||||
JavaScriptArray jsArray = new JavaScriptArray();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.EndArray:
|
||||
return jsArray;
|
||||
case JsonToken.Comment:
|
||||
break;
|
||||
default:
|
||||
object value = GetObject(reader, null);
|
||||
|
||||
jsArray.Add(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new JsonSerializationException("Unexpected end while deserializing array.");
|
||||
}
|
||||
|
||||
private JavaScriptObject PopulateJavaScriptObject(JsonReader reader)
|
||||
{
|
||||
JavaScriptObject jsObject = new JavaScriptObject();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.PropertyName:
|
||||
string memberName = reader.Value.ToString();
|
||||
|
||||
// move to the value token. skip comments
|
||||
do
|
||||
{
|
||||
if (!reader.Read())
|
||||
throw new JsonSerializationException("Unexpected end while deserializing object.");
|
||||
} while (reader.TokenType == JsonToken.Comment);
|
||||
|
||||
object value = GetObject(reader, null);
|
||||
|
||||
jsObject[memberName] = value;
|
||||
break;
|
||||
case JsonToken.EndObject:
|
||||
return jsObject;
|
||||
case JsonToken.Comment:
|
||||
break;
|
||||
default:
|
||||
throw new JsonSerializationException("Unexpected token while deserializing object: " + reader.TokenType);
|
||||
}
|
||||
}
|
||||
|
||||
throw new JsonSerializationException("Unexpected end while deserializing object.");
|
||||
}
|
||||
|
||||
private object GetObject(JsonReader reader, Type objectType)
|
||||
{
|
||||
_level++;
|
||||
|
||||
object value;
|
||||
JsonConverter converter;
|
||||
|
||||
if (HasMatchingConverter(objectType, out converter))
|
||||
{
|
||||
return converter.ReadJson(reader, objectType);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
// populate a typed object or generic dictionary/array
|
||||
// depending upon whether an objectType was supplied
|
||||
case JsonToken.StartObject:
|
||||
value = (objectType != null) ? PopulateObject(reader, objectType) : PopulateJavaScriptObject(reader);
|
||||
break;
|
||||
case JsonToken.StartArray:
|
||||
value = (objectType != null) ? PopulateList(reader, objectType) : PopulateJavaScriptArray(reader);
|
||||
break;
|
||||
case JsonToken.Integer:
|
||||
case JsonToken.Float:
|
||||
case JsonToken.String:
|
||||
case JsonToken.Boolean:
|
||||
case JsonToken.Date:
|
||||
value = EnsureType(reader.Value, objectType);
|
||||
break;
|
||||
case JsonToken.Constructor:
|
||||
value = reader.Value.ToString();
|
||||
break;
|
||||
case JsonToken.Null:
|
||||
case JsonToken.Undefined:
|
||||
value = null;
|
||||
break;
|
||||
default:
|
||||
throw new JsonSerializationException("Unexpected token whil deserializing object: " + reader.TokenType);
|
||||
}
|
||||
}
|
||||
|
||||
_level--;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private object EnsureType(object value, Type targetType)
|
||||
{
|
||||
// do something about null value when the targetType is a valuetype?
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
if (targetType == null)
|
||||
return value;
|
||||
|
||||
Type valueType = value.GetType();
|
||||
|
||||
// type of value and type of target don't match
|
||||
// attempt to convert value's type to target's type
|
||||
if (valueType != targetType)
|
||||
{
|
||||
TypeConverter targetConverter = TypeDescriptor.GetConverter(targetType);
|
||||
|
||||
if (!targetConverter.CanConvertFrom(valueType))
|
||||
{
|
||||
if (targetConverter.CanConvertFrom(typeof(string)))
|
||||
{
|
||||
string valueString = TypeDescriptor.GetConverter(value).ConvertToInvariantString(value);
|
||||
|
||||
return targetConverter.ConvertFromInvariantString(valueString);
|
||||
}
|
||||
|
||||
if (!targetType.IsAssignableFrom(valueType))
|
||||
throw new InvalidOperationException(string.Format("Cannot convert object of type '{0}' to type '{1}'", value.GetType(), targetType));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
return targetConverter.ConvertFrom(null, CultureInfo.InvariantCulture, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private MemberMappingCollection GetMemberMappings(Type objectType)
|
||||
{
|
||||
if (_typeMemberMappings == null)
|
||||
_typeMemberMappings = new Dictionary<Type, MemberMappingCollection>();
|
||||
|
||||
MemberMappingCollection memberMappings;
|
||||
|
||||
if (_typeMemberMappings.TryGetValue(objectType, out memberMappings))
|
||||
return memberMappings;
|
||||
|
||||
memberMappings = CreateMemberMappings(objectType);
|
||||
_typeMemberMappings[objectType] = memberMappings;
|
||||
|
||||
return memberMappings;
|
||||
}
|
||||
|
||||
private MemberMappingCollection CreateMemberMappings(Type objectType)
|
||||
{
|
||||
List<MemberInfo> members = ReflectionUtils.GetFieldsAndProperties(objectType, BindingFlags.Public | BindingFlags.Instance);
|
||||
MemberMappingCollection memberMappings = new MemberMappingCollection();
|
||||
|
||||
foreach (MemberInfo member in members)
|
||||
{
|
||||
string mappedName;
|
||||
|
||||
JsonPropertyAttribute propertyAttribute = ReflectionUtils.GetAttribute<JsonPropertyAttribute>(member, true);
|
||||
if (propertyAttribute != null)
|
||||
mappedName = propertyAttribute.PropertyName;
|
||||
else
|
||||
mappedName = member.Name;
|
||||
|
||||
bool ignored = member.IsDefined(typeof (JsonIgnoreAttribute), true);
|
||||
bool readable = ReflectionUtils.CanReadMemberValue(member);
|
||||
bool writable = ReflectionUtils.CanSetMemberValue(member);
|
||||
MemberMapping memberMapping = new MemberMapping(mappedName, member, ignored, readable, writable);
|
||||
|
||||
memberMappings.AddMapping(memberMapping);
|
||||
}
|
||||
|
||||
return memberMappings;
|
||||
}
|
||||
|
||||
private void SetObjectMember(JsonReader reader, object target, Type targetType, string memberName)
|
||||
{
|
||||
if (!reader.Read())
|
||||
throw new JsonSerializationException(string.Format("Unexpected end when setting {0}'s value.", memberName));
|
||||
|
||||
MemberMappingCollection memberMappings = GetMemberMappings(targetType);
|
||||
Type memberType;
|
||||
object value;
|
||||
|
||||
// test if a member with memberName exists on the type
|
||||
// otherwise test if target is a dictionary and assign value with the key if it is
|
||||
if (memberMappings.Contains(memberName))
|
||||
{
|
||||
MemberMapping memberMapping = memberMappings[memberName];
|
||||
|
||||
if (memberMapping.Ignored)
|
||||
return;
|
||||
|
||||
// ignore member if it is readonly
|
||||
if (!memberMapping.Writable)
|
||||
return;
|
||||
|
||||
// get the member's underlying type
|
||||
memberType = ReflectionUtils.GetMemberUnderlyingType(memberMapping.Member);
|
||||
|
||||
value = GetObject(reader, memberType);
|
||||
|
||||
ReflectionUtils.SetMemberValue(memberMapping.Member, target, value);
|
||||
}
|
||||
else if (typeof(IDictionary).IsAssignableFrom(targetType))
|
||||
{
|
||||
// attempt to get the IDictionary's type
|
||||
memberType = ReflectionUtils.GetDictionaryValueType(target.GetType());
|
||||
|
||||
value = GetObject(reader, memberType);
|
||||
|
||||
((IDictionary)target).Add(memberName, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonSerializationException(string.Format("Could not find member '{0}' on object of type '{1}'", memberName, targetType.GetType().Name));
|
||||
}
|
||||
}
|
||||
|
||||
private object PopulateList(JsonReader reader, Type objectType)
|
||||
{
|
||||
Type elementType = ReflectionUtils.GetListItemType(objectType);
|
||||
|
||||
IList populatedList = CollectionUtils.CreateAndPopulateList(objectType, delegate(IList list)
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.EndArray:
|
||||
return;
|
||||
case JsonToken.Comment:
|
||||
break;
|
||||
default:
|
||||
object value = GetObject(reader, elementType);
|
||||
|
||||
list.Add(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new JsonSerializationException("Unexpected end when deserializing array.");
|
||||
});
|
||||
|
||||
return populatedList;
|
||||
}
|
||||
|
||||
private object PopulateObject(JsonReader reader, Type objectType)
|
||||
{
|
||||
object newObject = Activator.CreateInstance(objectType);
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonToken.PropertyName:
|
||||
string memberName = reader.Value.ToString();
|
||||
|
||||
SetObjectMember(reader, newObject, objectType, memberName);
|
||||
break;
|
||||
case JsonToken.EndObject:
|
||||
return newObject;
|
||||
default:
|
||||
throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType);
|
||||
}
|
||||
}
|
||||
|
||||
throw new JsonSerializationException("Unexpected end when deserializing object.");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Serialize
|
||||
/// <summary>
|
||||
/// Serializes the specified <see cref="Object"/> and writes the Json structure
|
||||
/// to a <c>Stream</c> using the specified <see cref="TextWriter"/>.
|
||||
/// </summary>
|
||||
/// <param name="textWriter">The <see cref="TextWriter"/> used to write the Json structure.</param>
|
||||
/// <param name="value">The <see cref="Object"/> to serialize.</param>
|
||||
public void Serialize(TextWriter textWriter, object value)
|
||||
{
|
||||
Serialize(new JsonWriter(textWriter), value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the specified <see cref="Object"/> and writes the Json structure
|
||||
/// to a <c>Stream</c> using the specified <see cref="JsonWriter"/>.
|
||||
/// </summary>
|
||||
/// <param name="jsonWriter">The <see cref="JsonWriter"/> used to write the Json structure.</param>
|
||||
/// <param name="value">The <see cref="Object"/> to serialize.</param>
|
||||
public void Serialize(JsonWriter jsonWriter, object value)
|
||||
{
|
||||
if (jsonWriter == null)
|
||||
throw new ArgumentNullException("jsonWriter");
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
SerializeValue(jsonWriter, value);
|
||||
}
|
||||
|
||||
|
||||
private void SerializeValue(JsonWriter writer, object value)
|
||||
{
|
||||
JsonConverter converter;
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNull();
|
||||
}
|
||||
else if (HasMatchingConverter(value.GetType(), out converter))
|
||||
{
|
||||
converter.WriteJson(writer, value);
|
||||
}
|
||||
else if (value is IConvertible)
|
||||
{
|
||||
IConvertible convertible = value as IConvertible;
|
||||
|
||||
switch (convertible.GetTypeCode())
|
||||
{
|
||||
case TypeCode.String:
|
||||
writer.WriteValue((string)convertible);
|
||||
break;
|
||||
case TypeCode.Char:
|
||||
writer.WriteValue((char)convertible);
|
||||
break;
|
||||
case TypeCode.Boolean:
|
||||
writer.WriteValue((bool)convertible);
|
||||
break;
|
||||
case TypeCode.SByte:
|
||||
writer.WriteValue((sbyte)convertible);
|
||||
break;
|
||||
case TypeCode.Int16:
|
||||
writer.WriteValue((short)convertible);
|
||||
break;
|
||||
case TypeCode.UInt16:
|
||||
writer.WriteValue((ushort)convertible);
|
||||
break;
|
||||
case TypeCode.Int32:
|
||||
writer.WriteValue((int)convertible);
|
||||
break;
|
||||
case TypeCode.Byte:
|
||||
writer.WriteValue((byte)convertible);
|
||||
break;
|
||||
case TypeCode.UInt32:
|
||||
writer.WriteValue((uint)convertible);
|
||||
break;
|
||||
case TypeCode.Int64:
|
||||
writer.WriteValue((long)convertible);
|
||||
break;
|
||||
case TypeCode.UInt64:
|
||||
writer.WriteValue((ulong)convertible);
|
||||
break;
|
||||
case TypeCode.Single:
|
||||
writer.WriteValue((float)convertible);
|
||||
break;
|
||||
case TypeCode.Double:
|
||||
writer.WriteValue((double)convertible);
|
||||
break;
|
||||
case TypeCode.DateTime:
|
||||
writer.WriteValue((DateTime)convertible);
|
||||
break;
|
||||
case TypeCode.Decimal:
|
||||
writer.WriteValue((decimal)convertible);
|
||||
break;
|
||||
default:
|
||||
SerializeObject(writer, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (value is IList)
|
||||
{
|
||||
SerializeList(writer, (IList)value);
|
||||
}
|
||||
else if (value is IDictionary)
|
||||
{
|
||||
SerializeDictionary(writer, (IDictionary)value);
|
||||
}
|
||||
else if (value is ICollection)
|
||||
{
|
||||
SerializeCollection(writer, (ICollection)value);
|
||||
}
|
||||
else if (value is Identifier)
|
||||
{
|
||||
writer.WriteRaw(value.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
SerializeObject(writer, value);
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasMatchingConverter(Type type, out JsonConverter matchingConverter)
|
||||
{
|
||||
if (_converters != null)
|
||||
{
|
||||
for (int i = 0; i < _converters.Count; i++)
|
||||
{
|
||||
JsonConverter converter = _converters[i];
|
||||
|
||||
if (converter.CanConvert(type))
|
||||
{
|
||||
matchingConverter = converter;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matchingConverter = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private void WriteMemberInfoProperty(JsonWriter writer, object value, MemberInfo member, string propertyName)
|
||||
{
|
||||
if (!ReflectionUtils.IsIndexedProperty(member))
|
||||
{
|
||||
object memberValue = ReflectionUtils.GetMemberValue(member, value);
|
||||
|
||||
if (writer.SerializeStack.IndexOf(memberValue) != -1)
|
||||
{
|
||||
switch (_referenceLoopHandling)
|
||||
{
|
||||
case ReferenceLoopHandling.Error:
|
||||
throw new JsonSerializationException("Self referencing loop");
|
||||
case ReferenceLoopHandling.Ignore:
|
||||
// return from method
|
||||
return;
|
||||
case ReferenceLoopHandling.Serialize:
|
||||
// continue
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException(string.Format("Unexpected ReferenceLoopHandling value: '{0}'", _referenceLoopHandling));
|
||||
}
|
||||
}
|
||||
|
||||
writer.WritePropertyName(propertyName ?? member.Name);
|
||||
SerializeValue(writer, memberValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void SerializeObject(JsonWriter writer, object value)
|
||||
{
|
||||
Type objectType = value.GetType();
|
||||
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(objectType);
|
||||
|
||||
// use the objectType's TypeConverter if it has one and can convert to a string
|
||||
if (converter != null && !(converter is ComponentConverter) && converter.GetType() != typeof(TypeConverter))
|
||||
{
|
||||
if (converter.CanConvertTo(typeof(string)))
|
||||
{
|
||||
writer.WriteValue(converter.ConvertToInvariantString(value));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
writer.SerializeStack.Add(value);
|
||||
|
||||
writer.WriteStartObject();
|
||||
|
||||
MemberMappingCollection memberMappings = GetMemberMappings(objectType);
|
||||
|
||||
foreach (MemberMapping memberMapping in memberMappings)
|
||||
{
|
||||
if (!memberMapping.Ignored && memberMapping.Readable)
|
||||
WriteMemberInfoProperty(writer, value, memberMapping.Member, memberMapping.MappingName);
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
|
||||
writer.SerializeStack.Remove(value);
|
||||
}
|
||||
|
||||
private void SerializeCollection(JsonWriter writer, ICollection values)
|
||||
{
|
||||
object[] collectionValues = new object[values.Count];
|
||||
values.CopyTo(collectionValues, 0);
|
||||
|
||||
SerializeList(writer, collectionValues);
|
||||
}
|
||||
|
||||
private void SerializeList(JsonWriter writer, IList values)
|
||||
{
|
||||
writer.WriteStartArray();
|
||||
|
||||
for (int i = 0; i < values.Count; i++)
|
||||
{
|
||||
SerializeValue(writer, values[i]);
|
||||
}
|
||||
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
|
||||
private void SerializeDictionary(JsonWriter writer, IDictionary values)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
|
||||
foreach (DictionaryEntry entry in values)
|
||||
{
|
||||
writer.WritePropertyName(entry.Key.ToString());
|
||||
SerializeValue(writer, entry.Value);
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the type of Json token.
|
||||
/// </summary>
|
||||
public enum JsonToken
|
||||
{
|
||||
/// <summary>
|
||||
/// This is returned by the <see cref="JsonReader"/> if a <see cref="JsonReader.Read"/> method has not been called.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// An object start token.
|
||||
/// </summary>
|
||||
StartObject,
|
||||
/// <summary>
|
||||
/// An array start token.
|
||||
/// </summary>
|
||||
StartArray,
|
||||
/// <summary>
|
||||
/// An object property name.
|
||||
/// </summary>
|
||||
PropertyName,
|
||||
/// <summary>
|
||||
/// A comment.
|
||||
/// </summary>
|
||||
Comment,
|
||||
/// <summary>
|
||||
/// An interger.
|
||||
/// </summary>
|
||||
Integer,
|
||||
/// <summary>
|
||||
/// A float.
|
||||
/// </summary>
|
||||
Float,
|
||||
/// <summary>
|
||||
/// A string.
|
||||
/// </summary>
|
||||
String,
|
||||
/// <summary>
|
||||
/// A boolean.
|
||||
/// </summary>
|
||||
Boolean,
|
||||
/// <summary>
|
||||
/// A null token.
|
||||
/// </summary>
|
||||
Null,
|
||||
/// <summary>
|
||||
/// An undefined token.
|
||||
/// </summary>
|
||||
Undefined,
|
||||
/// <summary>
|
||||
/// An object end token.
|
||||
/// </summary>
|
||||
EndObject,
|
||||
/// <summary>
|
||||
/// An array end token.
|
||||
/// </summary>
|
||||
EndArray,
|
||||
/// <summary>
|
||||
/// A JavaScript object constructor.
|
||||
/// </summary>
|
||||
Constructor,
|
||||
/// <summary>
|
||||
/// A Date.
|
||||
/// </summary>
|
||||
Date
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,732 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
internal enum JsonType
|
||||
{
|
||||
Object,
|
||||
Array,
|
||||
None
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the state of the <see cref="JsonWriter"/>.
|
||||
/// </summary>
|
||||
public enum WriteState
|
||||
{
|
||||
/// <summary>
|
||||
/// An exception has been thrown, which has left the <see cref="JsonWriter"/> in an invalid state.
|
||||
/// You may call the <see cref="JsonWriter.Close"/> method to put the <see cref="JsonWriter"/> in the <c>Closed</c> state.
|
||||
/// Any other <see cref="JsonWriter"/> method calls results in an <see cref="InvalidOperationException"/> being thrown.
|
||||
/// </summary>
|
||||
Error,
|
||||
/// <summary>
|
||||
/// The <see cref="JsonWriter.Close"/> method has been called.
|
||||
/// </summary>
|
||||
Closed,
|
||||
/// <summary>
|
||||
/// An object is being written.
|
||||
/// </summary>
|
||||
Object,
|
||||
/// <summary>
|
||||
/// A array is being written.
|
||||
/// </summary>
|
||||
Array,
|
||||
/// <summary>
|
||||
/// A property is being written.
|
||||
/// </summary>
|
||||
Property,
|
||||
/// <summary>
|
||||
/// A write method has not been called.
|
||||
/// </summary>
|
||||
Start
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies formatting options for the <see cref="JsonWriter"/>.
|
||||
/// </summary>
|
||||
public enum Formatting
|
||||
{
|
||||
/// <summary>
|
||||
/// No special formatting is applied. This is the default.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Causes child objects to be indented according to the <see cref="JsonWriter.Indentation"/> and <see cref="JsonWriter.IndentChar"/> settings.
|
||||
/// </summary>
|
||||
Indented
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
|
||||
/// </summary>
|
||||
public class JsonWriter : IDisposable
|
||||
{
|
||||
private enum State
|
||||
{
|
||||
Start,
|
||||
Property,
|
||||
ObjectStart,
|
||||
Object,
|
||||
ArrayStart,
|
||||
Array,
|
||||
Closed,
|
||||
Error
|
||||
}
|
||||
|
||||
// array that gives a new state based on the current state an the token being written
|
||||
private static readonly State[,] stateArray = {
|
||||
// Start PropertyName ObjectStart Object ArrayStart Array Closed Error
|
||||
//
|
||||
/* None */{ State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error },
|
||||
/* StartObject */{ State.ObjectStart, State.ObjectStart, State.Error, State.Error, State.ObjectStart, State.ObjectStart, State.Error, State.Error },
|
||||
/* StartArray */{ State.ArrayStart, State.ArrayStart, State.Error, State.Error, State.ArrayStart, State.ArrayStart, State.Error, State.Error },
|
||||
/* StartProperty */{ State.Error, State.Error, State.Property, State.Property, State.Error, State.Error, State.Error, State.Error },
|
||||
/* Comment */{ State.Error, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Error, State.Error },
|
||||
/* Value */{ State.Error, State.Object, State.Error, State.Error, State.Array, State.Array, State.Error, State.Error },
|
||||
};
|
||||
|
||||
private int _top;
|
||||
private List<JsonType> _stack;
|
||||
private List<object> _serializeStack;
|
||||
private TextWriter _writer;
|
||||
private Formatting _formatting;
|
||||
private char _indentChar;
|
||||
private int _indentation;
|
||||
private char _quoteChar;
|
||||
private bool _quoteName;
|
||||
private State _currentState;
|
||||
|
||||
internal List<object> SerializeStack
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_serializeStack == null)
|
||||
_serializeStack = new List<object>();
|
||||
|
||||
return _serializeStack;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the state of the writer.
|
||||
/// </summary>
|
||||
public WriteState WriteState
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (_currentState)
|
||||
{
|
||||
case State.Error:
|
||||
return WriteState.Error;
|
||||
case State.Closed:
|
||||
return WriteState.Closed;
|
||||
case State.Object:
|
||||
case State.ObjectStart:
|
||||
return WriteState.Object;
|
||||
case State.Array:
|
||||
case State.ArrayStart:
|
||||
return WriteState.Array;
|
||||
case State.Property:
|
||||
return WriteState.Property;
|
||||
case State.Start:
|
||||
return WriteState.Start;
|
||||
default:
|
||||
throw new JsonWriterException("Invalid state: " + _currentState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates how the output is formatted.
|
||||
/// </summary>
|
||||
public Formatting Formatting
|
||||
{
|
||||
get { return _formatting; }
|
||||
set { _formatting = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets how many IndentChars to write for each level in the hierarchy when <paramref name="Formatting"/> is set to <c>Formatting.Indented</c>.
|
||||
/// </summary>
|
||||
public int Indentation
|
||||
{
|
||||
get { return _indentation; }
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
throw new ArgumentException("Indentation value must be greater than 0.");
|
||||
|
||||
_indentation = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets which character to use to quote attribute values.
|
||||
/// </summary>
|
||||
public char QuoteChar
|
||||
{
|
||||
get { return _quoteChar; }
|
||||
set
|
||||
{
|
||||
if (value != '"' && value != '\'')
|
||||
throw new ArgumentException(@"Invalid JavaScript string quote character. Valid quote characters are ' and "".");
|
||||
|
||||
_quoteChar = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets which character to use for indenting when <paramref name="Formatting"/> is set to <c>Formatting.Indented</c>.
|
||||
/// </summary>
|
||||
public char IndentChar
|
||||
{
|
||||
get { return _indentChar; }
|
||||
set { _indentChar = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether object names will be surrounded with quotes.
|
||||
/// </summary>
|
||||
public bool QuoteName
|
||||
{
|
||||
get { return _quoteName; }
|
||||
set { _quoteName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of the <c>JsonWriter</c> class using the specified <see cref="TextWriter"/>.
|
||||
/// </summary>
|
||||
/// <param name="textWriter">The <c>TextWriter</c> to write to.</param>
|
||||
public JsonWriter(TextWriter textWriter)
|
||||
{
|
||||
if (textWriter == null)
|
||||
throw new ArgumentNullException("textWriter");
|
||||
|
||||
_writer = textWriter;
|
||||
_quoteChar = '"';
|
||||
_quoteName = true;
|
||||
_indentChar = ' ';
|
||||
_indentation = 2;
|
||||
_formatting = Formatting.None;
|
||||
_stack = new List<JsonType>(1);
|
||||
_stack.Add(JsonType.None);
|
||||
_currentState = State.Start;
|
||||
}
|
||||
|
||||
private void Push(JsonType value)
|
||||
{
|
||||
_top++;
|
||||
if (_stack.Count <= _top)
|
||||
_stack.Add(value);
|
||||
else
|
||||
_stack[_top] = value;
|
||||
}
|
||||
|
||||
private JsonType Pop()
|
||||
{
|
||||
JsonType value = Peek();
|
||||
_top--;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private JsonType Peek()
|
||||
{
|
||||
return _stack[_top];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
|
||||
/// </summary>
|
||||
public void Flush()
|
||||
{
|
||||
_writer.Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes this stream and the underlying stream.
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
AutoCompleteAll();
|
||||
|
||||
_writer.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the beginning of a Json object.
|
||||
/// </summary>
|
||||
public void WriteStartObject()
|
||||
{
|
||||
AutoComplete(JsonToken.StartObject);
|
||||
|
||||
Push(JsonType.Object);
|
||||
|
||||
_writer.Write("{");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the end of a Json object.
|
||||
/// </summary>
|
||||
public void WriteEndObject()
|
||||
{
|
||||
AutoCompleteClose(JsonToken.EndObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the beginning of a Json array.
|
||||
/// </summary>
|
||||
public void WriteStartArray()
|
||||
{
|
||||
AutoComplete(JsonToken.StartArray);
|
||||
Push(JsonType.Array);
|
||||
_writer.Write("[");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the end of an array.
|
||||
/// </summary>
|
||||
public void WriteEndArray()
|
||||
{
|
||||
AutoCompleteClose(JsonToken.EndArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the property name of a name/value pair on a Json object.
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void WritePropertyName(string name)
|
||||
{
|
||||
//_objectStack.Push(new JsonObjectInfo(JsonType.Property));
|
||||
AutoComplete(JsonToken.PropertyName);
|
||||
|
||||
if (_quoteName)
|
||||
_writer.Write(_quoteChar);
|
||||
|
||||
_writer.Write(name);
|
||||
|
||||
if (_quoteName)
|
||||
_writer.Write(_quoteChar);
|
||||
|
||||
_writer.Write(':');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the end of the current Json object or array.
|
||||
/// </summary>
|
||||
public void WriteEnd()
|
||||
{
|
||||
WriteEnd(Peek());
|
||||
}
|
||||
|
||||
private void WriteEnd(JsonType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case JsonType.Object:
|
||||
WriteEndObject();
|
||||
break;
|
||||
case JsonType.Array:
|
||||
WriteEndArray();
|
||||
break;
|
||||
default:
|
||||
throw new JsonWriterException("Unexpected type when writing end: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
private void AutoCompleteAll()
|
||||
{
|
||||
while (_top > 0)
|
||||
{
|
||||
WriteEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private JsonType GetTypeForCloseToken(JsonToken token)
|
||||
{
|
||||
switch (token)
|
||||
{
|
||||
case JsonToken.EndObject:
|
||||
return JsonType.Object;
|
||||
case JsonToken.EndArray:
|
||||
return JsonType.Array;
|
||||
default:
|
||||
throw new JsonWriterException("No type for token: " + token);
|
||||
}
|
||||
}
|
||||
|
||||
private JsonToken GetCloseTokenForType(JsonType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case JsonType.Object:
|
||||
return JsonToken.EndObject;
|
||||
case JsonType.Array:
|
||||
return JsonToken.EndArray;
|
||||
default:
|
||||
throw new JsonWriterException("No close token for type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
private void AutoCompleteClose(JsonToken tokenBeingClosed)
|
||||
{
|
||||
// write closing symbol and calculate new state
|
||||
|
||||
int levelsToComplete = 0;
|
||||
|
||||
for (int i = 0; i < _top; i++)
|
||||
{
|
||||
int currentLevel = _top - i;
|
||||
|
||||
if (_stack[currentLevel] == GetTypeForCloseToken(tokenBeingClosed))
|
||||
{
|
||||
levelsToComplete = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (levelsToComplete == 0)
|
||||
throw new JsonWriterException("No token to close.");
|
||||
|
||||
for (int i = 0; i < levelsToComplete; i++)
|
||||
{
|
||||
JsonToken token = GetCloseTokenForType(Pop());
|
||||
|
||||
if (_currentState != State.ObjectStart && _currentState != State.ArrayStart)
|
||||
WriteIndent();
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case JsonToken.EndObject:
|
||||
_writer.Write("}");
|
||||
break;
|
||||
case JsonToken.EndArray:
|
||||
_writer.Write("]");
|
||||
break;
|
||||
default:
|
||||
throw new JsonWriterException("Invalid JsonToken: " + token);
|
||||
}
|
||||
}
|
||||
|
||||
JsonType currentLevelType = Peek();
|
||||
|
||||
switch (currentLevelType)
|
||||
{
|
||||
case JsonType.Object:
|
||||
_currentState = State.Object;
|
||||
break;
|
||||
case JsonType.Array:
|
||||
_currentState = State.Array;
|
||||
break;
|
||||
case JsonType.None:
|
||||
_currentState = State.Start;
|
||||
break;
|
||||
default:
|
||||
throw new JsonWriterException("Unknown JsonType: " + currentLevelType);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteIndent()
|
||||
{
|
||||
if (_formatting == Formatting.Indented)
|
||||
{
|
||||
_writer.Write(Environment.NewLine);
|
||||
// for each level of object...
|
||||
for (int i = 0; i < _top; i++)
|
||||
{
|
||||
// ...write the indent char the specified number of times
|
||||
for (int j = 0; j < _indentation; j++)
|
||||
{
|
||||
_writer.Write(_indentChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AutoComplete(JsonToken tokenBeingWritten)
|
||||
{
|
||||
int token;
|
||||
|
||||
switch (tokenBeingWritten)
|
||||
{
|
||||
default:
|
||||
token = (int)tokenBeingWritten;
|
||||
break;
|
||||
case JsonToken.Integer:
|
||||
case JsonToken.Float:
|
||||
case JsonToken.String:
|
||||
case JsonToken.Boolean:
|
||||
case JsonToken.Null:
|
||||
case JsonToken.Undefined:
|
||||
case JsonToken.Date:
|
||||
// a value is being written
|
||||
token = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
// gets new state based on the current state and what is being written
|
||||
State newState = stateArray[token, (int)_currentState];
|
||||
|
||||
if (newState == State.Error)
|
||||
throw new JsonWriterException(string.Format("Token {0} in state {1} would result in an invalid JavaScript object.", tokenBeingWritten.ToString(), _currentState.ToString()));
|
||||
|
||||
if ((_currentState == State.Object || _currentState == State.Array) && tokenBeingWritten != JsonToken.Comment)
|
||||
{
|
||||
_writer.Write(',');
|
||||
}
|
||||
else if (_currentState == State.Property)
|
||||
{
|
||||
if (_formatting == Formatting.Indented)
|
||||
_writer.Write(' ');
|
||||
}
|
||||
|
||||
if (tokenBeingWritten == JsonToken.PropertyName ||
|
||||
(WriteState == WriteState.Array))
|
||||
{
|
||||
WriteIndent();
|
||||
}
|
||||
|
||||
_currentState = newState;
|
||||
}
|
||||
|
||||
private void WriteValueInternal(string value, JsonToken token)
|
||||
{
|
||||
AutoComplete(token);
|
||||
|
||||
_writer.Write(value);
|
||||
}
|
||||
|
||||
#region WriteValue methods
|
||||
/// <summary>
|
||||
/// Writes a null value.
|
||||
/// </summary>
|
||||
public void WriteNull()
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.Null, JsonToken.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an undefined value.
|
||||
/// </summary>
|
||||
public void WriteUndefined()
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.Undefined, JsonToken.Undefined);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes raw JavaScript manually.
|
||||
/// </summary>
|
||||
/// <param name="javaScript">The raw JavaScript to write.</param>
|
||||
public void WriteRaw(string javaScript)
|
||||
{
|
||||
// hack. some 'raw' or 'other' token perhaps?
|
||||
WriteValueInternal(javaScript, JsonToken.Undefined);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="String"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="String"/> value to write.</param>
|
||||
public void WriteValue(string value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value, _quoteChar), JsonToken.String);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Int32"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Int32"/> value to write.</param>
|
||||
public void WriteValue(int value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="UInt32"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="UInt32"/> value to write.</param>
|
||||
public void WriteValue(uint value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Int64"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Int64"/> value to write.</param>
|
||||
public void WriteValue(long value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="UInt64"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="UInt64"/> value to write.</param>
|
||||
public void WriteValue(ulong value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Single"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Single"/> value to write.</param>
|
||||
public void WriteValue(float value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Double"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Double"/> value to write.</param>
|
||||
public void WriteValue(double value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Boolean"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Boolean"/> value to write.</param>
|
||||
public void WriteValue(bool value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Boolean);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Int16"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Int16"/> value to write.</param>
|
||||
public void WriteValue(short value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="UInt16"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="UInt16"/> value to write.</param>
|
||||
public void WriteValue(ushort value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Char"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Char"/> value to write.</param>
|
||||
public void WriteValue(char value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Byte"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Byte"/> value to write.</param>
|
||||
public void WriteValue(byte value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="SByte"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="SByte"/> value to write.</param>
|
||||
public void WriteValue(sbyte value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="Decimal"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Decimal"/> value to write.</param>
|
||||
public void WriteValue(decimal value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Float);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="DateTime"/> value.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="DateTime"/> value to write.</param>
|
||||
public void WriteValue(DateTime value)
|
||||
{
|
||||
WriteValueInternal(JavaScriptConvert.ToString(value), JsonToken.Date);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Writes out a comment <code>/*...*/</code> containing the specified text.
|
||||
/// </summary>
|
||||
/// <param name="text">Text to place inside the comment.</param>
|
||||
public void WriteComment(string text)
|
||||
{
|
||||
AutoComplete(JsonToken.Comment);
|
||||
|
||||
_writer.Write("/*");
|
||||
_writer.Write(text);
|
||||
_writer.Write("*/");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes out the given white space.
|
||||
/// </summary>
|
||||
/// <param name="ws">The string of white space characters.</param>
|
||||
public void WriteWhitespace(string ws)
|
||||
{
|
||||
if (ws != null)
|
||||
{
|
||||
if (!StringUtils.IsWhiteSpace(ws))
|
||||
throw new JsonWriterException("Only white space characters should be used.");
|
||||
|
||||
_writer.Write(ws);
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (WriteState != WriteState.Closed)
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception thrown when an error occurs while reading Json text.
|
||||
/// </summary>
|
||||
public class JsonWriterException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonWriterException"/> class.
|
||||
/// </summary>
|
||||
public JsonWriterException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonWriterException"/> class
|
||||
/// with a specified error message.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
public JsonWriterException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonWriterException"/> class
|
||||
/// with a specified error message and a reference to the inner exception that is the cause of this exception.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
|
||||
public JsonWriterException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
internal struct MemberMapping
|
||||
{
|
||||
private readonly string _mappingName;
|
||||
private readonly MemberInfo _member;
|
||||
private readonly bool _ignored;
|
||||
private readonly bool _readable;
|
||||
private readonly bool _writable;
|
||||
|
||||
public MemberMapping(string mappingName, MemberInfo member, bool ignored, bool readable, bool writable)
|
||||
{
|
||||
_mappingName = mappingName;
|
||||
_member = member;
|
||||
_ignored = ignored;
|
||||
_readable = readable;
|
||||
_writable = writable;
|
||||
}
|
||||
|
||||
public string MappingName
|
||||
{
|
||||
get { return _mappingName; }
|
||||
}
|
||||
|
||||
public MemberInfo Member
|
||||
{
|
||||
get { return _member; }
|
||||
}
|
||||
|
||||
public bool Ignored
|
||||
{
|
||||
get { return _ignored; }
|
||||
}
|
||||
|
||||
public bool Readable
|
||||
{
|
||||
get { return _readable; }
|
||||
}
|
||||
|
||||
public bool Writable
|
||||
{
|
||||
get { return _writable; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
internal class MemberMappingCollection : KeyedCollection<string, MemberMapping>
|
||||
{
|
||||
protected override string GetKeyForItem(MemberMapping item)
|
||||
{
|
||||
return item.MappingName;
|
||||
}
|
||||
|
||||
public void AddMapping(MemberMapping memberMapping)
|
||||
{
|
||||
if (Contains(memberMapping.MappingName))
|
||||
{
|
||||
// don't overwrite existing mapping with ignored mapping
|
||||
if (memberMapping.Ignored)
|
||||
return;
|
||||
|
||||
MemberMapping existingMemberMapping = this[memberMapping.MappingName];
|
||||
|
||||
if (!existingMemberMapping.Ignored)
|
||||
{
|
||||
throw new JsonSerializationException(
|
||||
string.Format(
|
||||
"A member with the name '{0}' already exists on {1}. Use the JsonPropertyAttribute to specify another name.",
|
||||
memberMapping.MappingName, memberMapping.Member.DeclaringType));
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove ignored mapping so it can be replaced in collection
|
||||
Remove(existingMemberMapping);
|
||||
}
|
||||
}
|
||||
|
||||
Add(memberMapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Newtonsoft.Json</RootNamespace>
|
||||
<AssemblyName>Newtonsoft.Json</AssemblyName>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>
|
||||
</AssemblyOriginatorKeyFile>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>bin\Debug\Newtonsoft.Json.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>bin\Release\Newtonsoft.Json.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Converters\AspNetAjaxDateTimeConverter.cs" />
|
||||
<Compile Include="Converters\XmlNodeConverter.cs" />
|
||||
<Compile Include="Converters\HtmlColorConverter.cs" />
|
||||
<Compile Include="JavaScriptParameters.cs" />
|
||||
<Compile Include="JavaScriptConstructor.cs" />
|
||||
<Compile Include="JsonPropertyAttribute.cs" />
|
||||
<Compile Include="JsonIgnoreAttribute.cs" />
|
||||
<Compile Include="JsonWriterException.cs" />
|
||||
<Compile Include="JsonReaderException.cs" />
|
||||
<Compile Include="Identifier.cs" />
|
||||
<Compile Include="JavaScriptArray.cs" />
|
||||
<Compile Include="JavaScriptObject.cs" />
|
||||
<Compile Include="JsonConverter.cs" />
|
||||
<Compile Include="JsonConverterCollection.cs" />
|
||||
<Compile Include="JsonReader.cs" />
|
||||
<Compile Include="JavaScriptConvert.cs" />
|
||||
<Compile Include="JsonSerializationException.cs" />
|
||||
<Compile Include="JsonSerializer.cs" />
|
||||
<Compile Include="MemberMapping.cs" />
|
||||
<Compile Include="MemberMappingCollection.cs" />
|
||||
<Compile Include="Utilities\JavaScriptUtils.cs" />
|
||||
<Compile Include="JsonToken.cs" />
|
||||
<Compile Include="JsonWriter.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StringBuffer.cs" />
|
||||
<Compile Include="Utilities\CollectionUtils.cs" />
|
||||
<Compile Include="Utilities\MathUtils.cs" />
|
||||
<Compile Include="Utilities\MiscellaneousUtils.cs" />
|
||||
<Compile Include="Utilities\ReflectionUtils.cs" />
|
||||
<Compile Include="Utilities\StringUtils.cs" />
|
||||
<Compile Include="Utilities\ValidationUtils.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,57 @@
|
||||
#region License
|
||||
// Copyright 2006 James Newton-King
|
||||
// http://www.newtonsoft.com
|
||||
//
|
||||
// This work is licensed under the Creative Commons Attribution 2.5 License
|
||||
// http://creativecommons.org/licenses/by/2.5/
|
||||
//
|
||||
// You are free:
|
||||
// * to copy, distribute, display, and perform the work
|
||||
// * to make derivative works
|
||||
// * to make commercial use of the work
|
||||
//
|
||||
// Under the following conditions:
|
||||
// * You must attribute the work in the manner specified by the author or licensor:
|
||||
// - If you find this component useful a link to http://www.newtonsoft.com would be appreciated.
|
||||
// * For any reuse or distribution, you must make clear to others the license terms of this work.
|
||||
// * Any of these conditions can be waived if you get permission from the copyright holder.
|
||||
#endregion
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Newtonsoft Json.NET")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Newtonsoft")]
|
||||
[assembly: AssemblyProduct("Newtonsoft Json.NET")]
|
||||
[assembly: AssemblyCopyright("Copyright © Newtonsoft 2006")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: AllowPartiallyTrustedCallers]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM componenets. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("9ca358aa-317b-4925-8ada-4a29e943a363")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.3.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.3.0.0")]
|
||||
@@ -0,0 +1,90 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds a string. Unlike StringBuilder this class lets you reuse it's internal buffer.
|
||||
/// </summary>
|
||||
internal class StringBuffer
|
||||
{
|
||||
private char[] _buffer;
|
||||
private int _position;
|
||||
|
||||
private static char[] _emptyBuffer = new char[0];
|
||||
|
||||
public int Position
|
||||
{
|
||||
get { return _position; }
|
||||
set { _position = value; }
|
||||
}
|
||||
|
||||
public StringBuffer()
|
||||
{
|
||||
_buffer = _emptyBuffer;
|
||||
}
|
||||
|
||||
public StringBuffer(int initalSize)
|
||||
{
|
||||
_buffer = new char[initalSize];
|
||||
}
|
||||
|
||||
public void Append(char value)
|
||||
{
|
||||
// test if the buffer array is large enough to take the value
|
||||
if (_position + 1 > _buffer.Length)
|
||||
{
|
||||
EnsureSize(1);
|
||||
}
|
||||
|
||||
// set value and increment poisition
|
||||
_buffer[_position++] = value;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_buffer = _emptyBuffer;
|
||||
_position = 0;
|
||||
}
|
||||
|
||||
private void EnsureSize(int appendLength)
|
||||
{
|
||||
char[] newBuffer = new char[_position + appendLength * 2];
|
||||
|
||||
Array.Copy(_buffer, newBuffer, _position);
|
||||
|
||||
_buffer = newBuffer;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return new string(_buffer, 0, _position);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class CollectionUtils
|
||||
{
|
||||
public static List<T> CreateList<T>(params T[] values)
|
||||
{
|
||||
return new List<T>(values);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the collection is null or empty.
|
||||
/// </summary>
|
||||
/// <param name="collection">The collection.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the collection is null or empty; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool IsNullOrEmpty(ICollection collection)
|
||||
{
|
||||
if (collection != null)
|
||||
{
|
||||
return (collection.Count == 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the collection is null or empty.
|
||||
/// </summary>
|
||||
/// <param name="collection">The collection.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the collection is null or empty; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool IsNullOrEmpty<T>(ICollection<T> collection)
|
||||
{
|
||||
if (collection != null)
|
||||
{
|
||||
return (collection.Count == 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the collection is null, empty or its contents are uninitialized values.
|
||||
/// </summary>
|
||||
/// <param name="list">The list.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the collection is null or empty or its contents are uninitialized values; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool IsNullOrEmptyOrDefault<T>(IList<T> list)
|
||||
{
|
||||
if (IsNullOrEmpty<T>(list))
|
||||
return true;
|
||||
|
||||
return ReflectionUtils.ItemsUnitializedValue<T>(list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes a slice of the specified list in between the start and end indexes.
|
||||
/// </summary>
|
||||
/// <param name="list">The list.</param>
|
||||
/// <param name="start">The start index.</param>
|
||||
/// <param name="end">The end index.</param>
|
||||
/// <returns>A slice of the list.</returns>
|
||||
public static IList<T> Slice<T>(IList<T> list, int? start, int? end)
|
||||
{
|
||||
return Slice<T>(list, start, end, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes a slice of the specified list in between the start and end indexes,
|
||||
/// getting every so many items based upon the step.
|
||||
/// </summary>
|
||||
/// <param name="list">The list.</param>
|
||||
/// <param name="start">The start index.</param>
|
||||
/// <param name="end">The end index.</param>
|
||||
/// <param name="step">The step.</param>
|
||||
/// <returns>A slice of the list.</returns>
|
||||
public static IList<T> Slice<T>(IList<T> list, int? start, int? end, int? step)
|
||||
{
|
||||
if (list == null)
|
||||
throw new ArgumentNullException("list");
|
||||
|
||||
if (step == 0)
|
||||
throw new ArgumentException("Step cannot be zero.", "step");
|
||||
|
||||
List<T> slicedList = new List<T>();
|
||||
|
||||
// nothing to slice
|
||||
if (list.Count == 0)
|
||||
return slicedList;
|
||||
|
||||
// set defaults for null arguments
|
||||
int s = step ?? 1;
|
||||
int startIndex = start ?? 0;
|
||||
int endIndex = end ?? list.Count;
|
||||
|
||||
// start from the end of the list if start is negitive
|
||||
startIndex = (startIndex < 0) ? list.Count + startIndex : startIndex;
|
||||
|
||||
// end from the start of the list if end is negitive
|
||||
endIndex = (endIndex < 0) ? list.Count + endIndex : endIndex;
|
||||
|
||||
// ensure indexes keep within collection bounds
|
||||
startIndex = Math.Max(startIndex, 0);
|
||||
endIndex = Math.Min(endIndex, list.Count - 1);
|
||||
|
||||
// loop between start and end indexes, incrementing by the step
|
||||
for (int i = startIndex; i < endIndex; i += s)
|
||||
{
|
||||
slicedList.Add(list[i]);
|
||||
}
|
||||
|
||||
return slicedList;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Group the collection using a function which returns the key.
|
||||
/// </summary>
|
||||
/// <param name="source">The source collection to group.</param>
|
||||
/// <param name="keySelector">The key selector.</param>
|
||||
/// <returns>A Dictionary with each key relating to a list of objects in a list grouped under it.</returns>
|
||||
public static Dictionary<K, List<V>> GroupBy<K, V>(ICollection<V> source, Func<V, K> keySelector)
|
||||
{
|
||||
if (keySelector == null)
|
||||
throw new ArgumentNullException("keySelector");
|
||||
|
||||
Dictionary<K, List<V>> groupedValues = new Dictionary<K, List<V>>();
|
||||
|
||||
foreach (V value in source)
|
||||
{
|
||||
// using delegate to get the value's key
|
||||
K key = keySelector(value);
|
||||
List<V> groupedValueList;
|
||||
|
||||
// add a list for grouped values if the key is not already in Dictionary
|
||||
if (!groupedValues.TryGetValue(key, out groupedValueList))
|
||||
{
|
||||
groupedValueList = new List<V>();
|
||||
groupedValues.Add(key, groupedValueList);
|
||||
}
|
||||
|
||||
groupedValueList.Add(value);
|
||||
}
|
||||
|
||||
return groupedValues;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the elements of the specified collection to the specified generic IList.
|
||||
/// </summary>
|
||||
/// <param name="initial">The list to add to.</param>
|
||||
/// <param name="collection">The collection of elements to add.</param>
|
||||
public static void AddRange<T>(IList<T> initial, IEnumerable<T> collection)
|
||||
{
|
||||
if (initial == null)
|
||||
throw new ArgumentNullException("initial");
|
||||
|
||||
if (collection == null)
|
||||
return;
|
||||
|
||||
foreach (T value in collection)
|
||||
{
|
||||
initial.Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<T> Distinct<T>(List<T> collection)
|
||||
{
|
||||
List<T> distinctList = new List<T>();
|
||||
|
||||
foreach (T value in collection)
|
||||
{
|
||||
if (!distinctList.Contains(value))
|
||||
distinctList.Add(value);
|
||||
}
|
||||
|
||||
return distinctList;
|
||||
}
|
||||
|
||||
public static List<List<T>> Flatten<T>(params IList<T>[] lists)
|
||||
{
|
||||
List<List<T>> flattened = new List<List<T>>();
|
||||
Dictionary<int, T> currentList = new Dictionary<int, T>();
|
||||
|
||||
Recurse<T>(new List<IList<T>>(lists), 0, currentList, flattened);
|
||||
|
||||
return flattened;
|
||||
}
|
||||
|
||||
private static void Recurse<T>(IList<IList<T>> global, int current, Dictionary<int, T> currentSet, List<List<T>> flattenedResult)
|
||||
{
|
||||
IList<T> currentArray = global[current];
|
||||
|
||||
for (int i = 0; i < currentArray.Count; i++)
|
||||
{
|
||||
currentSet[current] = currentArray[i];
|
||||
|
||||
if (current == global.Count - 1)
|
||||
{
|
||||
List<T> items = new List<T>();
|
||||
|
||||
for (int k = 0; k < currentSet.Count; k++)
|
||||
{
|
||||
items.Add(currentSet[k]);
|
||||
}
|
||||
|
||||
flattenedResult.Add(items);
|
||||
}
|
||||
else
|
||||
{
|
||||
Recurse(global, current + 1, currentSet, flattenedResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<T> CreateList<T>(ICollection collection)
|
||||
{
|
||||
if (collection == null)
|
||||
throw new ArgumentNullException("collection");
|
||||
|
||||
T[] array = new T[collection.Count];
|
||||
collection.CopyTo(array, 0);
|
||||
|
||||
return new List<T>(array);
|
||||
}
|
||||
|
||||
public static bool ListEquals<T>(IList<T> a, IList<T> b)
|
||||
{
|
||||
if (a == null || b == null)
|
||||
return (a == null && b == null);
|
||||
|
||||
if (a.Count != b.Count)
|
||||
return false;
|
||||
|
||||
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
|
||||
|
||||
for (int i = 0; i < a.Count; i++)
|
||||
{
|
||||
if (!comparer.Equals(a[i], b[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region GetSingleItem
|
||||
public static bool TryGetSingleItem<T>(IList<T> list, out T value)
|
||||
{
|
||||
return TryGetSingleItem<T>(list, false, out value);
|
||||
}
|
||||
|
||||
public static bool TryGetSingleItem<T>(IList<T> list, bool returnDefaultIfEmpty, out T value)
|
||||
{
|
||||
return MiscellaneousUtils.TryAction<T>(delegate { return GetSingleItem(list, returnDefaultIfEmpty); }, out value);
|
||||
}
|
||||
|
||||
public static T GetSingleItem<T>(IList<T> list)
|
||||
{
|
||||
return GetSingleItem<T>(list, false);
|
||||
}
|
||||
|
||||
public static T GetSingleItem<T>(IList<T> list, bool returnDefaultIfEmpty)
|
||||
{
|
||||
if (list.Count == 1)
|
||||
return list[0];
|
||||
else if (returnDefaultIfEmpty && list.Count == 0)
|
||||
return default(T);
|
||||
else
|
||||
throw new Exception(string.Format("Expected single {0} in list but got {1}.", typeof(T), list.Count));
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static IList<T> Minus<T>(IList<T> list, IList<T> minus)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(list, "list");
|
||||
|
||||
List<T> result = new List<T>(list.Count);
|
||||
foreach (T t in list)
|
||||
{
|
||||
if (minus == null || !minus.Contains(t))
|
||||
result.Add(t);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static T[] CreateArray<T>(IEnumerable<T> enumerable)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(enumerable, "enumerable");
|
||||
|
||||
if (enumerable is T[])
|
||||
return (T[])enumerable;
|
||||
|
||||
List<T> tempList = new List<T>(enumerable);
|
||||
return tempList.ToArray();
|
||||
}
|
||||
|
||||
public static object CreateGenericList(Type listType)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(listType, "listType");
|
||||
|
||||
return ReflectionUtils.CreateGeneric(typeof(List<>), listType);
|
||||
}
|
||||
|
||||
public static bool IsListType(Type type)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(type, "listType");
|
||||
|
||||
if (type.IsArray)
|
||||
return true;
|
||||
else if (typeof(IList).IsAssignableFrom(type))
|
||||
return true;
|
||||
else if (ReflectionUtils.IsSubClass(type, typeof(IList<>)))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public static IList CreateAndPopulateList(Type listType, Action<IList> populateList)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(listType, "listType");
|
||||
ValidationUtils.ArgumentNotNull(populateList, "populateList");
|
||||
|
||||
IList list;
|
||||
Type readOnlyCollectionType;
|
||||
bool isReadOnlyOrFixedSize = false;
|
||||
|
||||
if (listType.IsArray)
|
||||
{
|
||||
// have to use an arraylist when creating array
|
||||
// there is no way to know the size until it is finised
|
||||
list = new ArrayList();
|
||||
isReadOnlyOrFixedSize = true;
|
||||
}
|
||||
else if (ReflectionUtils.IsSubClass(listType, typeof(ReadOnlyCollection<>), out readOnlyCollectionType))
|
||||
{
|
||||
Type readOnlyCollectionContentsType = readOnlyCollectionType.GetGenericArguments()[0];
|
||||
Type genericEnumerable = ReflectionUtils.MakeGenericType(typeof(IEnumerable<>), readOnlyCollectionContentsType);
|
||||
bool suitableConstructor = false;
|
||||
|
||||
foreach (ConstructorInfo constructor in listType.GetConstructors())
|
||||
{
|
||||
IList<ParameterInfo> parameters = constructor.GetParameters();
|
||||
|
||||
if (parameters.Count == 1)
|
||||
{
|
||||
if (genericEnumerable.IsAssignableFrom(parameters[0].ParameterType))
|
||||
{
|
||||
suitableConstructor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!suitableConstructor)
|
||||
throw new Exception(string.Format("Readonly type {0} does not have a public constructor that takes a type that implements {1}.", listType, genericEnumerable));
|
||||
|
||||
// can't add or modify a readonly list
|
||||
// use List<T> and convert once populated
|
||||
list = (IList)CreateGenericList(readOnlyCollectionContentsType);
|
||||
isReadOnlyOrFixedSize = true;
|
||||
}
|
||||
else if (typeof(IList).IsAssignableFrom(listType) && ReflectionUtils.IsInstantiatableType(listType))
|
||||
{
|
||||
list = (IList)Activator.CreateInstance(listType);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(string.Format("Cannot create and populate list type {0}.", listType));
|
||||
}
|
||||
|
||||
populateList(list);
|
||||
|
||||
// create readonly and fixed sized collections using the temporary list
|
||||
if (isReadOnlyOrFixedSize)
|
||||
{
|
||||
if (listType.IsArray)
|
||||
list = ((ArrayList)list).ToArray(ReflectionUtils.GetListItemType(listType));
|
||||
else if (ReflectionUtils.IsSubClass(listType, typeof(ReadOnlyCollection<>)))
|
||||
list = (IList)Activator.CreateInstance(listType, list);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class JavaScriptUtils
|
||||
{
|
||||
public static string GetCallbackEventFunction(Page page, Control control)
|
||||
{
|
||||
string script = page.ClientScript.GetCallbackEventReference(control, "eventArgument", "eventCallback", "context", "errorCallback", true);
|
||||
|
||||
script = "function(eventArgument,eventCallback,context,errorCallback){" + script + "}";
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
public static string GetCallbackEventFunction(Page page, Control control, string argument)
|
||||
{
|
||||
string script = page.ClientScript.GetCallbackEventReference(control, "'" + argument + "'", "eventCallback", "context", "errorCallback", true);
|
||||
|
||||
script = "function(eventCallback,context,errorCallback){" + script + "}";
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
public static void WriteEscapedJavaScriptChar(TextWriter writer, char c, char delimiter)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\t':
|
||||
writer.Write(@"\t");
|
||||
break;
|
||||
case '\n':
|
||||
writer.Write(@"\n");
|
||||
break;
|
||||
case '\r':
|
||||
writer.Write(@"\r");
|
||||
break;
|
||||
case '\f':
|
||||
writer.Write(@"\f");
|
||||
break;
|
||||
case '\b':
|
||||
writer.Write(@"\b");
|
||||
break;
|
||||
case '\\':
|
||||
writer.Write(@"\\");
|
||||
break;
|
||||
//case '<':
|
||||
//case '>':
|
||||
//case '\'':
|
||||
// StringUtils.WriteCharAsUnicode(writer, c);
|
||||
// break;
|
||||
case '"':
|
||||
// only escape if this charater is being used as the delimiter
|
||||
writer.Write((delimiter == '"') ? "\\\"" : null);
|
||||
break;
|
||||
default:
|
||||
if (c > '\u001f')
|
||||
writer.Write(c);
|
||||
else
|
||||
StringUtils.WriteCharAsUnicode(writer, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteEscapedJavaScriptString(TextWriter writer, string value, char delimiter, bool appendDelimiters)
|
||||
{
|
||||
// leading delimiter
|
||||
if (appendDelimiters)
|
||||
writer.Write(delimiter);
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
WriteEscapedJavaScriptChar(writer, value[i], delimiter);
|
||||
}
|
||||
}
|
||||
|
||||
// trailing delimiter
|
||||
if (appendDelimiters)
|
||||
writer.Write(delimiter);
|
||||
}
|
||||
|
||||
public static string ToEscapedJavaScriptString(string value)
|
||||
{
|
||||
return ToEscapedJavaScriptString(value, '"', true);
|
||||
}
|
||||
|
||||
public static string ToEscapedJavaScriptString(string value, char delimiter, bool appendDelimiters)
|
||||
{
|
||||
using (StringWriter w = StringUtils.CreateStringWriter(StringUtils.GetLength(value) ?? 16))
|
||||
{
|
||||
WriteEscapedJavaScriptString(w, value, delimiter, appendDelimiters);
|
||||
return w.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class MathUtils
|
||||
{
|
||||
public static int HexToInt(char h)
|
||||
{
|
||||
if ((h >= '0') && (h <= '9'))
|
||||
{
|
||||
return (h - '0');
|
||||
}
|
||||
if ((h >= 'a') && (h <= 'f'))
|
||||
{
|
||||
return ((h - 'a') + 10);
|
||||
}
|
||||
if ((h >= 'A') && (h <= 'F'))
|
||||
{
|
||||
return ((h - 'A') + 10);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static char IntToHex(int n)
|
||||
{
|
||||
if (n <= 9)
|
||||
{
|
||||
return (char)(n + 48);
|
||||
}
|
||||
return (char)((n - 10) + 97);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal delegate void Action();
|
||||
internal delegate T Creator<T>();
|
||||
internal delegate T Func<A0, T>(A0 arg0);
|
||||
internal delegate T Func<A0, A1, T>(A0 arg0, A1 arg1);
|
||||
internal delegate T Func<A0, A1, A2, T>(A0 arg0, A1 arg1, A2 arg2);
|
||||
|
||||
internal static class MiscellaneousUtils
|
||||
{
|
||||
public static bool TryAction<T>(Creator<T> creator, out T output)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(creator, "creator");
|
||||
|
||||
try
|
||||
{
|
||||
output = creator();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
output = default(T);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetDescription(object value, out string description)
|
||||
{
|
||||
return TryAction<string>(delegate { return GetDescription(value); }, out description);
|
||||
}
|
||||
|
||||
public static string GetDescription(object o)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(o, "o");
|
||||
|
||||
ICustomAttributeProvider attributeProvider = o as ICustomAttributeProvider;
|
||||
|
||||
// object passed in isn't an attribute provider
|
||||
// if value is an enum value, get value field member, otherwise get values type
|
||||
if (attributeProvider == null)
|
||||
{
|
||||
Type valueType = o.GetType();
|
||||
|
||||
if (valueType.IsEnum)
|
||||
attributeProvider = valueType.GetField(o.ToString());
|
||||
else
|
||||
attributeProvider = valueType;
|
||||
}
|
||||
|
||||
DescriptionAttribute descriptionAttribute = ReflectionUtils.GetAttribute<DescriptionAttribute>(attributeProvider);
|
||||
|
||||
if (descriptionAttribute != null)
|
||||
return descriptionAttribute.Description;
|
||||
else
|
||||
throw new Exception(string.Format("No DescriptionAttribute on '{0}'.", o.GetType()));
|
||||
}
|
||||
|
||||
public static IList<string> GetDescriptions(IList values)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(values, "values");
|
||||
|
||||
string[] descriptions = new string[values.Count];
|
||||
|
||||
for (int i = 0; i < values.Count; i++)
|
||||
{
|
||||
descriptions[i] = GetDescription(values[i]);
|
||||
}
|
||||
|
||||
return descriptions;
|
||||
}
|
||||
|
||||
public static string ToString(object value)
|
||||
{
|
||||
return (value != null) ? value.ToString() : "{null}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,524 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class ReflectionUtils
|
||||
{
|
||||
public static Type GetObjectType(object v)
|
||||
{
|
||||
return (v != null) ? v.GetType() : null;
|
||||
}
|
||||
|
||||
public static bool IsInstantiatableType(Type t)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(t, "t");
|
||||
|
||||
if (t.IsAbstract || t.IsInterface || t.IsArray || t.IsGenericTypeDefinition || t == typeof(void))
|
||||
return false;
|
||||
|
||||
if (!HasDefaultConstructor(t))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool HasDefaultConstructor(Type t)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(t, "t");
|
||||
|
||||
if (t.IsValueType)
|
||||
return true;
|
||||
|
||||
return (t.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null) != null);
|
||||
}
|
||||
|
||||
public static bool IsNullable(Type t)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(t, "t");
|
||||
|
||||
if (t.IsValueType)
|
||||
return IsNullableType(t);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool IsNullableType(Type t)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(t, "t");
|
||||
|
||||
return (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
|
||||
}
|
||||
|
||||
//public static bool IsValueTypeUnitializedValue(ValueType value)
|
||||
//{
|
||||
// if (value == null)
|
||||
// return true;
|
||||
|
||||
// return value.Equals(CreateUnitializedValue(value.GetType()));
|
||||
//}
|
||||
|
||||
public static bool IsUnitializedValue(object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
object unitializedValue = CreateUnitializedValue(value.GetType());
|
||||
return value.Equals(unitializedValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static object CreateUnitializedValue(Type type)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(type, "type");
|
||||
|
||||
if (type.IsGenericTypeDefinition)
|
||||
throw new ArgumentException(string.Format("Type {0} is a generic type definition and cannot be instantiated.", type), "type");
|
||||
|
||||
if (type.IsClass || type.IsInterface || type == typeof(void))
|
||||
return null;
|
||||
else if (type.IsValueType)
|
||||
return Activator.CreateInstance(type);
|
||||
else
|
||||
throw new ArgumentException(string.Format("Type {0} cannot be instantiated.", type), "type");
|
||||
}
|
||||
|
||||
public static bool IsPropertyIndexed(PropertyInfo property)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(property, "property");
|
||||
|
||||
return !CollectionUtils.IsNullOrEmpty<ParameterInfo>(property.GetIndexParameters());
|
||||
}
|
||||
|
||||
public static bool IsSubClass(Type type, Type check)
|
||||
{
|
||||
Type implementingType;
|
||||
return IsSubClass(type, check, out implementingType);
|
||||
}
|
||||
|
||||
public static bool IsSubClass(Type type, Type check, out Type implementingType)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(type, "type");
|
||||
ValidationUtils.ArgumentNotNull(check, "check");
|
||||
|
||||
return IsSubClassInternal(type, type, check, out implementingType);
|
||||
}
|
||||
|
||||
private static bool IsSubClassInternal(Type initialType, Type currentType, Type check, out Type implementingType)
|
||||
{
|
||||
if (currentType == check)
|
||||
{
|
||||
implementingType = currentType;
|
||||
return true;
|
||||
}
|
||||
|
||||
// don't get interfaces for an interface unless the initial type is an interface
|
||||
if (check.IsInterface && (initialType.IsInterface || currentType == initialType))
|
||||
{
|
||||
foreach (Type t in currentType.GetInterfaces())
|
||||
{
|
||||
if (IsSubClassInternal(initialType, t, check, out implementingType))
|
||||
{
|
||||
// don't return the interface itself, return it's implementor
|
||||
if (check == implementingType)
|
||||
implementingType = currentType;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentType.IsGenericType && !currentType.IsGenericTypeDefinition)
|
||||
{
|
||||
if (IsSubClassInternal(initialType, currentType.GetGenericTypeDefinition(), check, out implementingType))
|
||||
{
|
||||
implementingType = currentType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentType.BaseType == null)
|
||||
{
|
||||
implementingType = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsSubClassInternal(initialType, currentType.BaseType, check, out implementingType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the typed list's items.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>The type of the typed list's items.</returns>
|
||||
public static Type GetListItemType(Type type)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(type, "type");
|
||||
Type genericListType;
|
||||
|
||||
if (type.IsArray)
|
||||
{
|
||||
return type.GetElementType();
|
||||
}
|
||||
else if (IsSubClass(type, typeof(IList<>), out genericListType))
|
||||
{
|
||||
if (genericListType.IsGenericTypeDefinition)
|
||||
throw new Exception(string.Format("Type {0} is not a list.", type));
|
||||
|
||||
return genericListType.GetGenericArguments()[0];
|
||||
}
|
||||
else if (typeof(IList).IsAssignableFrom(type))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(string.Format("Type {0} is not a list.", type));
|
||||
}
|
||||
}
|
||||
|
||||
public static Type GetDictionaryValueType(Type type)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(type, "type");
|
||||
|
||||
Type genericDictionaryType;
|
||||
if (IsSubClass(type, typeof(IDictionary<,>), out genericDictionaryType))
|
||||
{
|
||||
if (genericDictionaryType.IsGenericTypeDefinition)
|
||||
throw new Exception(string.Format("Type {0} is not a dictionary.", type));
|
||||
|
||||
return genericDictionaryType.GetGenericArguments()[1];
|
||||
}
|
||||
else if (typeof(IDictionary).IsAssignableFrom(type))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(string.Format("Type {0} is not a dictionary.", type));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the list's items are their unitialized value.
|
||||
/// </summary>
|
||||
/// <param name="list">The list.</param>
|
||||
/// <returns>Whether the list's items are their unitialized value</returns>
|
||||
public static bool ItemsUnitializedValue<T>(IList<T> list)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(list, "list");
|
||||
|
||||
Type elementType = GetListItemType(list.GetType());
|
||||
|
||||
if (elementType.IsValueType)
|
||||
{
|
||||
object unitializedValue = CreateUnitializedValue(elementType);
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (!list[i].Equals(unitializedValue))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (elementType.IsClass)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
object value = list[i];
|
||||
|
||||
if (value != null)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(string.Format("Type {0} is neither a ValueType or a Class.", elementType));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the member's underlying type.
|
||||
/// </summary>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <returns>The underlying type of the member.</returns>
|
||||
public static Type GetMemberUnderlyingType(MemberInfo member)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(member, "member");
|
||||
|
||||
switch (member.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
return ((FieldInfo)member).FieldType;
|
||||
case MemberTypes.Property:
|
||||
return ((PropertyInfo)member).PropertyType;
|
||||
case MemberTypes.Event:
|
||||
return ((EventInfo)member).EventHandlerType;
|
||||
default:
|
||||
throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", "member");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the member is an indexed property.
|
||||
/// </summary>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the member is an indexed property; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool IsIndexedProperty(MemberInfo member)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(member, "member");
|
||||
|
||||
PropertyInfo propertyInfo = member as PropertyInfo;
|
||||
|
||||
if (propertyInfo != null)
|
||||
return IsIndexedProperty(propertyInfo);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property is an indexed property.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the property is an indexed property; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool IsIndexedProperty(PropertyInfo property)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(property, "property");
|
||||
|
||||
return (property.GetIndexParameters().Length > 0);
|
||||
}
|
||||
|
||||
public static MemberInfo GetMember(Type type, string name, MemberTypes memberTypes)
|
||||
{
|
||||
return GetMember(type, name, memberTypes, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
|
||||
}
|
||||
|
||||
public static MemberInfo GetMember(Type type, string name, MemberTypes memberTypes, BindingFlags bindingAttr)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(type, "type");
|
||||
ValidationUtils.ArgumentNotNull(name, "name");
|
||||
|
||||
MemberInfo[] result = type.GetMember(name, memberTypes, bindingAttr);
|
||||
|
||||
return CollectionUtils.GetSingleItem<MemberInfo>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the member's value on the object.
|
||||
/// </summary>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <returns>The member's value on the object.</returns>
|
||||
public static object GetMemberValue(MemberInfo member, object target)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(member, "member");
|
||||
ValidationUtils.ArgumentNotNull(target, "target");
|
||||
|
||||
switch (member.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
return ((FieldInfo)member).GetValue(target);
|
||||
case MemberTypes.Property:
|
||||
try
|
||||
{
|
||||
return ((PropertyInfo)member).GetValue(target, null);
|
||||
}
|
||||
catch (TargetParameterCountException e)
|
||||
{
|
||||
throw new ArgumentException(string.Format("MemberInfo '{0}' has index parameters", member.Name), "member", e);
|
||||
}
|
||||
default:
|
||||
throw new ArgumentException(string.Format("MemberInfo '{0}' is not of type FieldInfo or PropertyInfo", member.Name), "member");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the member's value on the target object.
|
||||
/// </summary>
|
||||
/// <param name="member">The member.</param>
|
||||
/// <param name="target">The target.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
public static void SetMemberValue(MemberInfo member, object target, object value)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(member, "member");
|
||||
ValidationUtils.ArgumentNotNull(target, "target");
|
||||
|
||||
switch (member.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
((FieldInfo)member).SetValue(target, value);
|
||||
break;
|
||||
case MemberTypes.Property:
|
||||
((PropertyInfo)member).SetValue(target, value, null);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException(string.Format("MemberInfo '{0}' must be of type FieldInfo or PropertyInfo", member.Name), "member");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified MemberInfo can be read.
|
||||
/// </summary>
|
||||
/// <param name="member">The MemberInfo to determine whether can be read.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified MemberInfo can be read; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool CanReadMemberValue(MemberInfo member)
|
||||
{
|
||||
switch (member.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
return true;
|
||||
case MemberTypes.Property:
|
||||
return ((PropertyInfo)member).CanRead;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified MemberInfo can be set.
|
||||
/// </summary>
|
||||
/// <param name="member">The MemberInfo to determine whether can be set.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified MemberInfo can be set; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool CanSetMemberValue(MemberInfo member)
|
||||
{
|
||||
switch (member.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
return true;
|
||||
case MemberTypes.Property:
|
||||
return ((PropertyInfo)member).CanWrite;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<MemberInfo> GetFieldsAndProperties<T>(BindingFlags bindingAttr)
|
||||
{
|
||||
return GetFieldsAndProperties(typeof(T), bindingAttr);
|
||||
}
|
||||
|
||||
public static List<MemberInfo> GetFieldsAndProperties(Type type, BindingFlags bindingAttr)
|
||||
{
|
||||
List<MemberInfo> targetMembers = new List<MemberInfo>();
|
||||
|
||||
targetMembers.AddRange(type.GetFields(bindingAttr));
|
||||
targetMembers.AddRange(type.GetProperties(bindingAttr));
|
||||
|
||||
return targetMembers;
|
||||
}
|
||||
|
||||
public static T GetAttribute<T>(ICustomAttributeProvider attributeProvider) where T : Attribute
|
||||
{
|
||||
return GetAttribute<T>(attributeProvider, true);
|
||||
}
|
||||
|
||||
public static T GetAttribute<T>(ICustomAttributeProvider attributeProvider, bool inherit) where T : Attribute
|
||||
{
|
||||
T[] attributes = GetAttributes<T>(attributeProvider, inherit);
|
||||
|
||||
return CollectionUtils.GetSingleItem(attributes, true);
|
||||
}
|
||||
|
||||
public static T[] GetAttributes<T>(ICustomAttributeProvider attributeProvider, bool inherit) where T : Attribute
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider");
|
||||
|
||||
return (T[])attributeProvider.GetCustomAttributes(typeof(T), inherit);
|
||||
}
|
||||
|
||||
public static string GetNameAndAssessmblyName(Type t)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(t, "t");
|
||||
|
||||
return t.FullName + ", " + t.Assembly.GetName().Name;
|
||||
}
|
||||
|
||||
public static List<MemberInfo> FindMembers(Type targetType, MemberTypes memberType, BindingFlags bindingAttr, MemberFilter filter, object filterCriteria)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(targetType, "targetType");
|
||||
|
||||
List<MemberInfo> memberInfos = new List<MemberInfo>(targetType.FindMembers(memberType, bindingAttr, filter, filterCriteria));
|
||||
|
||||
// fix weirdness with FieldInfos only being returned for the current Type
|
||||
// find base type fields and add them to result
|
||||
if ((memberType & MemberTypes.Field) != 0
|
||||
&& (bindingAttr & BindingFlags.NonPublic) != 0)
|
||||
{
|
||||
// modify flags to not search for public fields
|
||||
BindingFlags nonPublicBindingAttr = bindingAttr ^ BindingFlags.Public;
|
||||
|
||||
while ((targetType = targetType.BaseType) != null)
|
||||
{
|
||||
memberInfos.AddRange(targetType.FindMembers(MemberTypes.Field, nonPublicBindingAttr, filter, filterCriteria));
|
||||
}
|
||||
}
|
||||
|
||||
return memberInfos;
|
||||
}
|
||||
|
||||
public static Type MakeGenericType(Type genericTypeDefinition, params Type[] innerTypes)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(genericTypeDefinition, "genericTypeDefinition");
|
||||
ValidationUtils.ArgumentNotNullOrEmpty<Type>(innerTypes, "innerTypes");
|
||||
ValidationUtils.ArgumentConditionTrue(genericTypeDefinition.IsGenericTypeDefinition, "genericTypeDefinition", string.Format("Type {0} is not a generic type definition.", genericTypeDefinition));
|
||||
|
||||
return genericTypeDefinition.MakeGenericType(innerTypes);
|
||||
}
|
||||
|
||||
public static object CreateGeneric(Type genericTypeDefinition, Type innerType, params object[] args)
|
||||
{
|
||||
return CreateGeneric(genericTypeDefinition, new Type[] { innerType }, args);
|
||||
}
|
||||
|
||||
public static object CreateGeneric(Type genericTypeDefinition, IList<Type> innerTypes, params object[] args)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(genericTypeDefinition, "genericTypeDefinition");
|
||||
ValidationUtils.ArgumentNotNullOrEmpty(innerTypes, "innerTypes");
|
||||
|
||||
Type specificType = MakeGenericType(genericTypeDefinition, CollectionUtils.CreateArray(innerTypes));
|
||||
|
||||
return Activator.CreateInstance(specificType, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlTypes;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class StringUtils
|
||||
{
|
||||
public const string CarriageReturnLineFeed = "\r\n";
|
||||
public const string Empty = "";
|
||||
public const char CarriageReturn = '\r';
|
||||
public const char LineFeed = '\n';
|
||||
public const char Tab = '\t';
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the string contains white space.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to test for white space.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the string contains white space; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool ContainsWhiteSpace(string s)
|
||||
{
|
||||
if (s == null)
|
||||
throw new ArgumentNullException("s");
|
||||
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
if (char.IsWhiteSpace(s[i]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the string is all white space. Empty string will return false.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to test whether it is all white space.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the string is all white space; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool IsWhiteSpace(string s)
|
||||
{
|
||||
if (s == null)
|
||||
throw new ArgumentNullException("s");
|
||||
|
||||
if (s.Length == 0)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
if (!char.IsWhiteSpace(s[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures the target string ends with the specified string.
|
||||
/// </summary>
|
||||
/// <param name="target">The target.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>The target string with the value string at the end.</returns>
|
||||
public static string EnsureEndsWith(string target, string value)
|
||||
{
|
||||
if (target == null)
|
||||
throw new ArgumentNullException("target");
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (target.Length >= value.Length)
|
||||
{
|
||||
if (string.Compare(target, target.Length - value.Length, value, 0, value.Length, StringComparison.OrdinalIgnoreCase) ==
|
||||
0)
|
||||
return target;
|
||||
|
||||
string trimmedString = target.TrimEnd(null);
|
||||
|
||||
if (string.Compare(trimmedString, trimmedString.Length - value.Length, value, 0, value.Length,
|
||||
StringComparison.OrdinalIgnoreCase) == 0)
|
||||
return target;
|
||||
}
|
||||
|
||||
return target + value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the SqlString is null or empty.
|
||||
/// </summary>
|
||||
/// <param name="s">The string.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the SqlString is null or empty; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool IsNullOrEmpty(SqlString s)
|
||||
{
|
||||
if (s.IsNull)
|
||||
return true;
|
||||
else
|
||||
return string.IsNullOrEmpty(s.Value);
|
||||
}
|
||||
|
||||
public static bool IsNullOrEmptyOrWhiteSpace(string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s))
|
||||
return true;
|
||||
else if (IsWhiteSpace(s))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an action if the string is not null or empty.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="action">The action to perform.</param>
|
||||
public static void IfNotNullOrEmpty(string value, Action<string> action)
|
||||
{
|
||||
IfNotNullOrEmpty(value, action, null);
|
||||
}
|
||||
|
||||
private static void IfNotNullOrEmpty(string value, Action<string> trueAction, Action<string> falseAction)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
if (trueAction != null)
|
||||
trueAction(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (falseAction != null)
|
||||
falseAction(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indents the specified string.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to indent.</param>
|
||||
/// <param name="indentation">The number of characters to indent by.</param>
|
||||
/// <returns></returns>
|
||||
public static string Indent(string s, int indentation)
|
||||
{
|
||||
return Indent(s, indentation, ' ');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indents the specified string.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to indent.</param>
|
||||
/// <param name="indentation">The number of characters to indent by.</param>
|
||||
/// <param name="indentChar">The indent character.</param>
|
||||
/// <returns></returns>
|
||||
public static string Indent(string s, int indentation, char indentChar)
|
||||
{
|
||||
if (s == null)
|
||||
throw new ArgumentNullException("s");
|
||||
|
||||
if (indentation <= 0)
|
||||
throw new ArgumentException("Must be greater than zero.", "indentation");
|
||||
|
||||
StringReader sr = new StringReader(s);
|
||||
StringWriter sw = new StringWriter();
|
||||
|
||||
ActionTextReaderLine(sr, sw, delegate(TextWriter tw, string line)
|
||||
{
|
||||
tw.Write(new string(indentChar, indentation));
|
||||
tw.Write(line);
|
||||
});
|
||||
|
||||
return sw.ToString();
|
||||
}
|
||||
|
||||
private delegate void ActionLine(TextWriter textWriter, string line);
|
||||
|
||||
private static void ActionTextReaderLine(TextReader textReader, TextWriter textWriter, ActionLine lineAction)
|
||||
{
|
||||
string line;
|
||||
bool firstLine = true;
|
||||
while ((line = textReader.ReadLine()) != null)
|
||||
{
|
||||
if (!firstLine)
|
||||
textWriter.WriteLine();
|
||||
else
|
||||
firstLine = false;
|
||||
|
||||
lineAction(textWriter, line);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Numbers the lines.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to number.</param>
|
||||
/// <returns></returns>
|
||||
public static string NumberLines(string s)
|
||||
{
|
||||
if (s == null)
|
||||
throw new ArgumentNullException("s");
|
||||
|
||||
StringReader sr = new StringReader(s);
|
||||
StringWriter sw = new StringWriter();
|
||||
|
||||
int lineNumber = 1;
|
||||
|
||||
ActionTextReaderLine(sr, sw, delegate(TextWriter tw, string line)
|
||||
{
|
||||
tw.Write(lineNumber.ToString().PadLeft(4));
|
||||
tw.Write(". ");
|
||||
tw.Write(line);
|
||||
|
||||
lineNumber++;
|
||||
});
|
||||
|
||||
return sw.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nulls an empty string.
|
||||
/// </summary>
|
||||
/// <param name="s">The string.</param>
|
||||
/// <returns>Null if the string was null, otherwise the string unchanged.</returns>
|
||||
public static string NullEmptyString(string s)
|
||||
{
|
||||
return (string.IsNullOrEmpty(s)) ? null : s;
|
||||
}
|
||||
|
||||
public static string ReplaceNewLines(string s, string replacement)
|
||||
{
|
||||
StringReader sr = new StringReader(s);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
bool first = true;
|
||||
|
||||
string line;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
sb.Append(replacement);
|
||||
|
||||
sb.Append(line);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string RemoveHtml(string s)
|
||||
{
|
||||
return RemoveHtmlInternal(s, null);
|
||||
}
|
||||
|
||||
public static string RemoveHtml(string s, IList<string> removeTags)
|
||||
{
|
||||
if (removeTags == null)
|
||||
throw new ArgumentNullException("removeTags");
|
||||
|
||||
return RemoveHtmlInternal(s, removeTags);
|
||||
}
|
||||
|
||||
private static string RemoveHtmlInternal(string s, IList<string> removeTags)
|
||||
{
|
||||
List<string> removeTagsUpper = null;
|
||||
|
||||
if (removeTags != null)
|
||||
{
|
||||
removeTagsUpper = new List<string>(removeTags.Count);
|
||||
|
||||
foreach (string tag in removeTags)
|
||||
{
|
||||
removeTagsUpper.Add(tag.ToUpperInvariant());
|
||||
}
|
||||
}
|
||||
|
||||
Regex anyTag = new Regex(@"<[/]{0,1}\s*(?<tag>\w*)\s*(?<attr>.*?=['""].*?[""'])*?\s*[/]{0,1}>", RegexOptions.Compiled);
|
||||
|
||||
return anyTag.Replace(s, delegate(Match match)
|
||||
{
|
||||
string tag = match.Groups["tag"].Value.ToUpperInvariant();
|
||||
|
||||
if (removeTagsUpper == null)
|
||||
return string.Empty;
|
||||
else if (removeTagsUpper.Contains(tag))
|
||||
return string.Empty;
|
||||
else
|
||||
return match.Value;
|
||||
});
|
||||
}
|
||||
|
||||
public static string Truncate(string s, int maximumLength)
|
||||
{
|
||||
return Truncate(s, maximumLength, "...");
|
||||
}
|
||||
|
||||
public static string Truncate(string s, int maximumLength, string suffix)
|
||||
{
|
||||
if (suffix == null)
|
||||
throw new ArgumentNullException("suffix");
|
||||
|
||||
if (maximumLength <= 0)
|
||||
throw new ArgumentException("Maximum length must be greater than zero.", "maximumLength");
|
||||
|
||||
int subStringLength = maximumLength - suffix.Length;
|
||||
|
||||
if (subStringLength <= 0)
|
||||
throw new ArgumentException("Length of suffix string is greater or equal to maximumLength");
|
||||
|
||||
if (s != null && s.Length > maximumLength)
|
||||
{
|
||||
string truncatedString = s.Substring(0, subStringLength);
|
||||
// incase the last character is a space
|
||||
truncatedString = truncatedString.Trim();
|
||||
truncatedString += suffix;
|
||||
|
||||
return truncatedString;
|
||||
}
|
||||
else
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
public static StringWriter CreateStringWriter(int capacity)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(capacity);
|
||||
StringWriter sw = new StringWriter(sb);
|
||||
|
||||
return sw;
|
||||
}
|
||||
|
||||
public static int? GetLength(string value)
|
||||
{
|
||||
if (value == null)
|
||||
return null;
|
||||
else
|
||||
return value.Length;
|
||||
}
|
||||
|
||||
public static string ToCharAsUnicode(char c)
|
||||
{
|
||||
using (StringWriter w = new StringWriter())
|
||||
{
|
||||
WriteCharAsUnicode(w, c);
|
||||
return w.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteCharAsUnicode(TextWriter writer, char c)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(writer, "writer");
|
||||
|
||||
char h1 = MathUtils.IntToHex((c >> 12) & '\x000f');
|
||||
char h2 = MathUtils.IntToHex((c >> 8) & '\x000f');
|
||||
char h3 = MathUtils.IntToHex((c >> 4) & '\x000f');
|
||||
char h4 = MathUtils.IntToHex(c & '\x000f');
|
||||
|
||||
writer.Write('\\');
|
||||
writer.Write('u');
|
||||
writer.Write(h1);
|
||||
writer.Write(h2);
|
||||
writer.Write(h3);
|
||||
writer.Write(h4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class ValidationUtils
|
||||
{
|
||||
public const string EmailAddressRegex = @"^([a-zA-Z0-9_'+*$%\^&!\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9:]{2,4})+$";
|
||||
public const string CurrencyRegex = @"(^\$?(?!0,?\d)\d{1,3}(,?\d{3})*(\.\d\d)?)$";
|
||||
public const string DateRegex =
|
||||
@"^(((0?[1-9]|[12]\d|3[01])[\.\-\/](0?[13578]|1[02])[\.\-\/]((1[6-9]|[2-9]\d)?\d{2}|\d))|((0?[1-9]|[12]\d|30)[\.\-\/](0?[13456789]|1[012])[\.\-\/]((1[6-9]|[2-9]\d)?\d{2}|\d))|((0?[1-9]|1\d|2[0-8])[\.\-\/]0?2[\.\-\/]((1[6-9]|[2-9]\d)?\d{2}|\d))|(29[\.\-\/]0?2[\.\-\/]((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)|00|[048])))$";
|
||||
public const string NumericRegex = @"\d*";
|
||||
|
||||
public static void ArgumentNotNullOrEmpty(string value, string parameterName)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(parameterName);
|
||||
|
||||
if (value.Length == 0)
|
||||
throw new ArgumentException(string.Format("'{0}' cannot be empty.", parameterName), parameterName);
|
||||
}
|
||||
|
||||
public static void ArgumentNotNullOrEmptyOrWhitespace(string value, string parameterName)
|
||||
{
|
||||
ArgumentNotNullOrEmpty(value, parameterName);
|
||||
|
||||
if (StringUtils.IsWhiteSpace(value))
|
||||
throw new ArgumentException(string.Format("'{0}' cannot only be whitespace.", parameterName), parameterName);
|
||||
}
|
||||
|
||||
public static void ArgumentTypeIsEnum(Type enumType, string parameterName)
|
||||
{
|
||||
ArgumentNotNull(enumType, "enumType");
|
||||
|
||||
if (!enumType.IsEnum)
|
||||
throw new ArgumentException(string.Format("Type {0} is not an Enum.", enumType), parameterName);
|
||||
}
|
||||
|
||||
public static void ArgumentNotNullOrEmpty<T>(ICollection<T> collection, string parameterName)
|
||||
{
|
||||
ArgumentNotNullOrEmpty<T>(collection, parameterName, string.Format("Collection '{0}' cannot be empty.", parameterName));
|
||||
}
|
||||
|
||||
public static void ArgumentNotNullOrEmpty<T>(ICollection<T> collection, string parameterName, string message)
|
||||
{
|
||||
if (collection == null)
|
||||
throw new ArgumentNullException(parameterName);
|
||||
|
||||
if (collection.Count == 0)
|
||||
throw new ArgumentException(message, parameterName);
|
||||
}
|
||||
|
||||
public static void ArgumentNotNullOrEmpty(ICollection collection, string parameterName)
|
||||
{
|
||||
ArgumentNotNullOrEmpty(collection, parameterName, string.Format("Collection '{0}' cannot be empty.", parameterName));
|
||||
}
|
||||
|
||||
public static void ArgumentNotNullOrEmpty(ICollection collection, string parameterName, string message)
|
||||
{
|
||||
if (collection == null)
|
||||
throw new ArgumentNullException(parameterName);
|
||||
|
||||
if (collection.Count == 0)
|
||||
throw new ArgumentException(message, parameterName);
|
||||
}
|
||||
|
||||
public static void ArgumentNotNull(object value, string parameterName)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(parameterName);
|
||||
}
|
||||
|
||||
public static void ArgumentNotNegative(int value, string parameterName)
|
||||
{
|
||||
if (value <= 0)
|
||||
throw new ArgumentOutOfRangeException(parameterName, value, "Argument cannot be negative.");
|
||||
}
|
||||
|
||||
public static void ArgumentNotNegative(int value, string parameterName, string message)
|
||||
{
|
||||
if (value <= 0)
|
||||
throw new ArgumentOutOfRangeException(parameterName, value, message);
|
||||
}
|
||||
|
||||
public static void ArgumentNotZero(int value, string parameterName)
|
||||
{
|
||||
if (value == 0)
|
||||
throw new ArgumentOutOfRangeException(parameterName, value, "Argument cannot be zero.");
|
||||
}
|
||||
|
||||
public static void ArgumentNotZero(int value, string parameterName, string message)
|
||||
{
|
||||
if (value == 0)
|
||||
throw new ArgumentOutOfRangeException(parameterName, value, message);
|
||||
}
|
||||
|
||||
public static void ArgumentIsPositive<T>(T value, string parameterName) where T : struct, IComparable<T>
|
||||
{
|
||||
if (value.CompareTo(default(T)) != 1)
|
||||
throw new ArgumentOutOfRangeException(parameterName, value, "Positive number required.");
|
||||
}
|
||||
|
||||
public static void ArgumentIsPositive(int value, string parameterName, string message)
|
||||
{
|
||||
if (value > 0)
|
||||
throw new ArgumentOutOfRangeException(parameterName, value, message);
|
||||
}
|
||||
|
||||
public static void ObjectNotDisposed(bool disposed, Type objectType)
|
||||
{
|
||||
if (disposed)
|
||||
throw new ObjectDisposedException(objectType.Name);
|
||||
}
|
||||
|
||||
public static void ArgumentConditionTrue(bool condition, string parameterName, string message)
|
||||
{
|
||||
if (!condition)
|
||||
throw new ArgumentException(message, parameterName);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user