Json.Net学习笔记
通常當用到大的Json文檔的時候,你可能只對其中的一小個片段信息感興趣。這種情況下你想把Json.Net轉換為.Net 對象就會讓人很困擾,因為你必須為Json的整個結果定義一個.Net的類。
使用Json.Net很容易避開這個問題。在把它們傳遞到Json.Net序列化器之前,你可以使用Linq to Json 提取Json中你想要序列化的一些片段。
?string googleSearchText = @"{
????????????????? ""responseData"": {
??????????????????? ""results"": [
????????????????????? {
??????????????????????? ""GsearchResultClass"": ""GwebSearch"",
??????????????????????? ""unescapedUrl"": ""http://en.wikipedia.org/wiki/Paris_Hilton"",
??????????????????????? ""url"": ""http://en.wikipedia.org/wiki/Paris_Hilton"",
??????????????????????? ""visibleUrl"": ""en.wikipedia.org"",
??????????????????????? ""cacheUrl"": ""http://www.google.com/search?q=cache:TwrPfhd22hYJ:en.wikipedia.org"",
??????????????????????? ""title"": ""<b>Paris Hilton</b> - Wikipedia, the free encyclopedia"",
??????????????????????? ""titleNoFormatting"": ""Paris Hilton - Wikipedia, the free encyclopedia"",
??????????????????????? ""content"": ""[1] In 2006, she released her debut album...""
????????????????????? },
????????????????????? {
??????????????????????? ""GsearchResultClass"": ""GwebSearch"",
??????????????????????? ""unescapedUrl"": ""http://www.imdb.com/name/nm0385296/"",
??????????????????????? ""url"": ""http://www.imdb.com/name/nm0385296/"",
??????????????????????? ""visibleUrl"": ""www.imdb.com"",
??????????????????????? ""cacheUrl"": ""http://www.google.com/search?q=cache:1i34KkqnsooJ:www.imdb.com"",
??????????????????????? ""title"": ""<b>Paris Hilton</b>"",
??????????????????????? ""titleNoFormatting"": ""Paris Hilton"",
??????????????????????? ""content"": ""Self: Zoolander. Socialite <b>Paris Hilton</b>...""
????????????????????? }
??????????????????? ],
??????????????????? ""cursor"": {
????????????????????? ""pages"": [
??????????????????????? {
????????????????????????? ""start"": ""0"",
????????????????????????? ""label"": 1
??????????????????????? },
??????????????????????? {
????????????????????????? ""start"": ""4"",
????????????????????????? ""label"": 2
??????????????????????? },
??????????????????????? {
????????????????????????? ""start"": ""8"",
????????????????????????? ""label"": 3
??????????????????????? },
??????????????????????? {
????????????????????????? ""start"": ""12"",
????????????????????????? ""label"": 4
??????????????????????? }
????????????????????? ],
????????????????????? ""estimatedResultCount"": ""59600000"",
????????????????????? ""currentPageIndex"": 0,
????????????????????? ""moreResultsUrl"": ""http://www.google.com/search?oe=utf8&ie=utf8...""
??????????????????? }
????????????????? },
????????????????? ""responseDetails"": null,
????????????????? ""responseStatus"": 200
??????????????? }";
??????????? JObject googleSearch = JObject.Parse(googleSearchText);
??????????? // get JSON result objects into a list
??????????? IList<JToken> results = googleSearch["responseData"]["results"].Children().ToList();
??????????? // serialize JSON results into .NET objects
??????????? IList<SearchResult> searchResults = new List<SearchResult>();
??????????? foreach (JToken result in results)
??????????? {
??????????????? SearchResult searchResult = JsonConvert.DeserializeObject<SearchResult>(result.ToString());
??????????????? searchResults.Add(searchResult);
??????????? }
??????????? // Title = <b>Paris Hilton</b> - Wikipedia, the free encyclopedia
??????????? // Content = [1] In 2006, she released her debut album...
??????????? // Url =?http://en.wikipedia.org/wiki/Paris_Hilton
??????????? // Title = <b>Paris Hilton</b>
??????????? // Content = Self: Zoolander. Socialite <b>Paris Hilton</b>...
??????????? // Url =?http://www.imdb.com/name/nm0385296/
為了解決多余的Json這個問題,Json.Net有一系列內置的選項可以進行調整。
->JsonIgnoreAttribute and DataMemberAttribute
默認情況下,在Json創建的時候Json.Net會包含所有類級別的public屬性和字段。添加JsonIgnoreAttribute到屬性上,告訴序列化器序列化時跳過它。
?public class Car
??? {
??????? // included in JSON
??????? public string Model { get; set; }
??????? public DateTime Year { get; set; }
??????? public List<string> Features { get; set; }
??????? // ignored
??????? [JsonIgnore]
??????? public DateTime LastModified { get; set; }
??? }
如果類有很多屬性,你只想序列化它的一小部分,添加JsonIgore到所有其他的屬性上會比較冗余,也比較容易出錯。有一種用來處理這種情況的方法,添加DataContractAttribute到類上,添加DataMemberAttribute到需要被序列化的屬性上。與使用JsonIgnoreAttribute的opt-out序列化相比,opt-in序列化僅僅你標記的屬性被需列化。
using System.Runtime.Serialization;
? [DataContract]
??? public class Computer
??? {
??????? // included in JSON
??????? [DataMember]
??????? public string Name { get; set; }
??????? [DataMember]
??????? public decimal SalePrice { get; set; }
??????? // ignored
??????? public string Manufacture { get; set; }
??????? public int StockCount { get; set; }
??????? public decimal WholeSalePrice { get; set; }
??????? public DateTime NextShipmentDate { get; set; }
??? }
->Formatting
Json序列化時,用可選參數Formatting.Indented生成良好的顯示格式,可讀性更好。另一方面,Formatting.None會跳過不必要的空格和換行符,讓Json的結果更小。生成的顯示格式更加緊湊,也許效率更高。
->NullValueHandling
?? 在序列化器中NullVlaueHandling是可選的。它控制序列化器如何處理值為null的屬性。通過設置NullValueHandling.Ignore值,序列化器會跳過值為null的屬性。
? public class Movie
??? {
??????? public string Name { get; set; }
??????? public string Description { get; set; }
??????? public string Classification { get; set; }
??????? public string Studio { get; set; }
??????? public DateTime? ReleaseDate { get; set; }
??????? public List<string> ReleaseCountries { get; set; }
??? }
測試1:
?????????? Movie movie = new Movie();
??????????? movie.Name = "Bad Boys III";
??????????? movie.Description = "It's no Bad Boys";
??????????? string included = JsonConvert.SerializeObject(movie,
????????????? Formatting.Indented,
????????????? new JsonSerializerSettings { });
??????????? Console.WriteLine(included);
輸出結果:
{
? "Name": "Bad Boys III",
? "Description": "It's no Bad Boys",
? "Classification": null,
? "Studio": null,
? "ReleaseDate": null,
? "ReleaseCountries": null
}
測試2:
?????????? string ignored = JsonConvert.SerializeObject(movie,
????????????? Formatting.Indented,
????????????? new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
??????????? Console.WriteLine(ignored);
輸出結果:
{
? "Name": "Bad Boys III",
? "Description": "It's no Bad Boys"
}
NullValueHandling也可以在單獨的屬性上用JsonPropertyAttribute進行定制。使用JsonPropertyAttribute時設置的NullValueHandling值會在Json序列化器中為該屬性進行重寫。
->DefaultValuehandling
?? 在序列化器中DefaultValuehandling是可選的。它控制序列化器如何處理帶有默認值的屬性。通過設置DefaultValuehandling.Ignore值,序列化器會跳過帶有默認值的屬性。對于引用類型為null,對于值類型,如int和DateTime,序列化器將跳過默認未初使化值的值類型。
? Json.Net也允許你通過DefaultValueAttribute自定義默認值,例如:如果一個字符串類型的屬性Department在它的默認狀態下總是返回一個空字符,但是在你的Json對象中你不想要那個空字符串,你可以在Department上使用空字符串參數標記DefaultValueAttribute,這意味著Department在序列化時不再寫入Json中,除非它有非空值。
? public class Invoice
??? {
??????? public string Company { get; set; }
??????? public decimal Amount { get; set; }
??????? // false is default value of bool
??????? public bool Paid { get; set; }
??????? // null is default value of nullable
??????? public DateTime? PaidDate { get; set; }
??????? // customize default values
??????? [DefaultValue(30)]
??????? public int FollowUpDays { get; set; }
??????? [DefaultValue("")]
??????? public string FollowUpEmailAddress { get; set; }
??? }
測試1:
???????????Invoice invoice = new Invoice
??????????? {
??????????????? Company = "Acme Ltd.",
??????????????? Amount = 50.0m,
??????????????? Paid = false,
??????????????? FollowUpDays = 30,
??????????????? FollowUpEmailAddress = string.Empty,
??????????????? PaidDate = null
??????????? };
??????????? string includedDefaultValue = JsonConvert.SerializeObject(invoice,
????????????? Formatting.Indented,
????????????? new JsonSerializerSettings { });
??????????? Console.WriteLine(includedDefaultValue);
輸出結果:
{
? "Company": "Acme Ltd.",
? "Amount": 50.0,
? "Paid": false,
? "PaidDate": null,
? "FollowUpDays": 30,
? "FollowUpEmailAddress": ""
}
測試2:
?????????? ?string ignoredDefaultValue = JsonConvert.SerializeObject(invoice,
????????????? Formatting.Indented,
????????????? new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });
??????????? Console.WriteLine(ignoredDefaultValue);
輸出結果:
{
? "Company": "Acme Ltd.",
? "Amount": 50.0,
? "Paid": false//??
}
DefaultValueHandling也可以在單獨的屬性上用JsonPropertyAttribute進行定制。使用JsonPropertyAttribute時設置的DefaultValueHandling值會在Json序列化器中為該屬性進行重寫。
->IContractResolver
? 為了獲得更多的靈活性,IContractResolver接口提供了定制.Net對象序列化為Json的每一個方面,包括在運行時改變序列化的行為。
?public class DynamicContractResolver : DefaultContractResolver
??? {
??????? private readonly char _startingWithChar;
??????? public DynamicContractResolver(char startingWithChar)
??????? {
??????????? _startingWithChar = startingWithChar;
??????? }
??????? protected override IList<JsonProperty> CreateProperties(JsonObjectContract contract)
??????? {
??????????? IList<JsonProperty> properties = base.CreateProperties(contract);
??????????? // only serializer properties that start with the specified character
??????????? properties =
????????????? properties.Where(p => p.PropertyName.StartsWith(_startingWithChar.ToString())).ToList();
??????????? return properties;
??????? }
??? }
??? public class Book
??? {
??????? public string BookName { get; set; }
??????? public decimal BookPrice { get; set; }
??????? public string AuthorName { get; set; }
??????? public int AuthorAge { get; set; }
??????? public string AuthorCountry { get; set; }
??? }
測試:
?????????? Book book = new Book
??????????? {
??????????????? BookName = "The Gathering Storm",
??????????????? BookPrice = 16.19m,
??????????????? AuthorName = "Brandon Sanderson",
??????????????? AuthorAge = 34,
??????????????? AuthorCountry = "United States of America"
??????????? };
??????????? string startingWithA = JsonConvert.SerializeObject(book, Formatting.Indented,
????????????? new JsonSerializerSettings { ContractResolver = new DynamicContractResolver('A') });
??????????? Console.WriteLine(startingWithA);
??????????? // {
??????????? //?? "AuthorName": "Brandon Sanderson",
??????????? //?? "AuthorAge": 34,
??????????? //?? "AuthorCountry": "United States of America"
??????????? // }
??????????? string startingWithB = JsonConvert.SerializeObject(book, Formatting.Indented,
????????????? new JsonSerializerSettings { ContractResolver = new DynamicContractResolver('B') });
??????????? Console.WriteLine(startingWithA);
??????????? // {
??????????? //?? "BookName": "The Gathering Storm",
??????????? //?? "BookPrice": 16.19
??????????? // }
IContractResolver接口提供了一種方法去定制序列化器如何去序列化和反序列化.Net對象為Json對象
實現IContractResolver接口,然后為Json序列化器分配一個實例對象,這樣你就可以控制對象是否被序列化為Json對象或者Json數組、對象的成員應該被序列化成什么、如何被序列化、及他們被誰調用等。
->DefaultContractResolver
???DefaultContractResolver是序列化器默認的解析器,它以虛函數的形式提供了很多擴展功能,可以被覆寫(overriden).
->CamelCasePropertyNamesContractResolver
?? CamelCasePropertyNamesContractResolver繼承自DefaultContractResolver,并且簡單的覆寫了Json屬性名為camel命名規則的形式(首字母小寫)
? public class Product
??? {
??????? public string Name { get; set; }
??????? public decimal Price { get; set; }
??????? public DateTime ExpiryDate { get; set; }
??????? public string[] Sizes { get; set; }
??? }
測試:
?Product product = new Product
??????????? {
??????????????? ExpiryDate = new DateTime(2010, 12, 20, 18, 1, 0, DateTimeKind.Utc),
??????????????? Name = "Widget",
??????????????? Price = 9.99m,
??????????????? Sizes = new[] { "Small", "Medium", "Large" }
??????????? };
??????????? string json = JsonConvert.SerializeObject(
??????????????????????????? product,
??????????????????????????? Formatting.Indented,
??????????????????????????? new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }
???????????????????????????? );
??????????? Console.WriteLine(json);
輸出結果:
{
? "name": "Widget",
? "price": 9.99,
? "expiryDate": "\/Date(1292868060000)\/",
? "sizes": [
??? "Small",
??? "Medium",
??? "Large"
? ]
CustomCreationConverter是一個在序列化過程中提供自定方式去創建一個對象的Json轉換器,一旦對象被創建,它將被序列化器填充值。
?public interface IPerson
??? {
??????? string FirstName { get; set; }
??????? string LastName { get; set; }
??????? DateTime BirthDate { get; set; }
??? }
??? public class Employee : IPerson
??? {
??????? public string FirstName { get; set; }
??????? public string LastName { get; set; }
??????? public DateTime BirthDate { get; set; }
??????? public string Department { get; set; }
??????? public string JobTitle { get; set; }
??? }
??? public class PersonConverter : CustomCreationConverter<IPerson>
??? {
??????? public override IPerson Create(Type objectType)
??????? {
??????????? return new Employee();
??????? }
??? }
這是一個非常簡單的例子。更復雜的場景可能包含一個對象工廠或者服務定位器(service locator)用來在運行時解析這個對象。
測試:???
????? string json = @"[
????????????? {
??????????????? ""FirstName"": ""Maurice"",
??????????????? ""LastName"": ""Moss"",
??????????????? ""BirthDate"": ""\/Date(252291661000)\/"",
??????????????? ""Department"": ""IT"",
??????????????? ""JobTitle"": ""Support""
????????????? },
????????????? {
??????????????? ""FirstName"": ""Jen"",
??????????????? ""LastName"": ""Barber"",
??????????????? ""BirthDate"": ""\/Date(258771661000)\/"",
??????????????? ""Department"": ""IT"",
??????????????? ""JobTitle"": ""Manager""
????????????? }
??????????? ]";
??????????? List<IPerson> people = JsonConvert.DeserializeObject<List<IPerson>>(json, new PersonConverter());
??????????? IPerson person = people[0];
??????????? Console.WriteLine(person.GetType());// CustomCreationConverterTest.Employee??????????
??????????? Console.WriteLine(person.FirstName);// Maurice
??????????? Employee employee = (Employee)person;
??????????? Console.WriteLine(employee.JobTitle);// Support
Json.Net支持在序列化和反序列化的過程中進行異常處理。異常處理讓您捕獲一個異常,您可以選擇是否處理它,繼續序列化或者讓異常拋給上一層,在你的應用程序中被拋出。
異常處理通過兩個方法來定義:the Error event on JsonSerializer 和 OnErrorAttribute
>Error Event
? error event是一個建立在JsonSerializer 上的異常處理.當序列化或者反序列化JSON時,任何有異常拋出的情況error event都會被觸發.就像建立在JsonSerializer上的所有設置一樣,它也可以在JsonSerializerSettings 上進行設置從而傳遞給JsonConvert的序列化方法.
示例:
?List<string> errors = new List<string>();
??????????? List<DateTime> c = JsonConvert.DeserializeObject<List<DateTime>>(@"[
????????????????? ""2010-12-19T00:00:00Z"",
????????????????? ""I am not a date and will error!"",
????????????????? [
??????????????????? 1
????????????????? ],
????????????????? ""2011-01-01T00:00:00Z"",
????????????????? null,
????????????????? ""2010-12-25T00:00:00Z""
????????????????? ]", new JsonSerializerSettings()
??????????????????????? {
??????????????????????????? Error = delegate(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e)
??????????????????????????? {
??????????????????????????????? errors.Add(e.ErrorContext.Error.Message);
??????????????????????????????? e.ErrorContext.Handled = true;
??????????????????????????? },
??????????????????????????? Converters = { new IsoDateTimeConverter() }
??????????????????????? });
??????????? foreach (DateTime t in c)
??????????? {
??????????????? Console.WriteLine(t.ToString());
??????????? }
??????????? //2010-12-19 00:00:00
??????????? //2011-01-01 00:00:00
??????????? //2010-12-25 00:00:00
??????????? foreach (string err in errors)
??????????? {
??????????????? Console.WriteLine(err);
??????????? }
??????????? //The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.
??????????? //Unexpected token parsing date. Expected String, got StartArray.
??????????? //Cannot convert null value to System.DateTime.
? 在這個例子中我們把一個Json數組反序列化為一個DateTime的集合,在JsonSerializerSettings中有一個hander被賦值成了error event ,它用來記錄error message,并標記這個error為已處理(handled).
反序列化JSON的結果是三個被成功反序列化的日期和三個error messages:一個是不正確的格式,"I am not a date and will error!",一個是嵌套了JSON數組,最后一個是null值,因為定義的list不允許有可空類型的DateTime.這個事件處理已經記錄了這些信息,Json.Net在序列化時繼續進行(沒有因為異常而停止),因為這些錯誤已經被標記為已處理。
?? 值得注意的是,在Json.Net進行異常處理時,沒有處理的異常將會被拋到上一層,并在它的每個parent觸發事件,例如:在序列化若干對象的集合時,一個未處理的異常將被觸發兩次,首先在對象上,然后在集合上。這樣就會讓您在處理異常的時候,選擇在它發生的地方,或者是它的一個parent上。
?JsonSerializer serializer = new JsonSerializer();
??????????? serializer.Error += delegate(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e)
??????????? {
??????????????? // only log an error once
??????????????? if (e.CurrentObject == e.ErrorContext.OriginalObject)
??????????????????? errors.Add(e.ErrorContext.Error.Message);
??????????? };
如果您不是立即處理一個異常,僅僅是想針對它完成一次操作,您可以驗證一下ErrorEventArg's CurrentObject是否等于OriginalObject.OriginalObject是拋出異常的對象,CurrentObject是事件被觸發的對象.他們只會在第一次(事件被OriginalObject觸發時)相等.
>OnErrorAttribute
?OnErrorAttribute的工作方式非常像其他Json.Net支持的.NET serialization attributes ,簡單地把它標記在帶有正確參數(一個StreamingContext和一個ErrorContext)的方法上就可以使用了,與方法的名字沒有關系。
示例:
? public class PersonError
??? {
??????? private List<string> _roles;
??????? public string Name { get; set; }
??????? public int Age { get; set; }
??????? public List<string> Roles
??????? {
??????????? get
??????????? {
??????????????? if (_roles == null)
??????????????????? throw new Exception("Roles not loaded!");
??????????????? return _roles;
??????????? }
??????????? set { _roles = value; }
??????? }
??????? public string Title { get; set; }
??????? [OnError]
??????? internal void OnError(StreamingContext context, ErrorContext errorContext)
??????? {
??????????? errorContext.Handled = true;
??????? }
??? }
在這個例子中,當_roles沒有被設置值時訪問Roles屬性將會拋出一個異常.在序列化Roles屬性時,異常處理的方法將設置error為handled,從而允許Json.Net繼續序列化這個類。
測試:
?PersonError person = new PersonError
??????????? {
??????????????? Name = "George Michael Bluth",
??????????????? Age = 16,
??????????????? Roles = null,
??????????????? Title = "Mister Manager"
??????????? };
??????????? string json = JsonConvert.SerializeObject(person, Formatting.Indented);
??????????? Console.WriteLine(json);
輸出:
??????????? {
????????????? "Name": "George Michael Bluth",
????????????? "Age": 16,
????????????? "Title": "Mister Manager"
??????????? }
?
posted @ 2011-06-11 15:10 資源收集 閱讀(57) 評論(0)?編輯 Json.Net學習筆記(十) 保持對象引用默認情況下,Json.Net將通過對象的值來序列化它遇到的所有對象。如果工個list包含兩個Person引用,這兩個引用都指向同一個對象,Json序列化器將輸出每一個引用的所有名稱和值。
定義類:
? public class Person
??? {
??????? public DateTime BirthDate { get; set; }
??????? public DateTime LastModified { get; set; }
??????? public string Name { get; set; }
??? }
測試:
???????? Person p = new Person()
??????????? {
??????????????? BirthDate = new DateTime(1985, 11, 27, 0, 0, 0, DateTimeKind.Utc),
??????????????? LastModified = new DateTime(2010, 12, 20, 0, 0, 0, DateTimeKind.Utc),
??????????????? Name = "James"
??????????? };
??????????? List<Person> people = new List<Person>();
??????????? people.Add(p);
??????????? people.Add(p);
??????????? string json = JsonConvert.SerializeObject(people, Formatting.Indented);
??????????? Console.WriteLine(json);
輸出結果:
[
? {
??? "BirthDate": "\/Date(501897600000)\/",
??? "LastModified": "\/Date(1292803200000)\/",
??? "Name": "James"
? },
? {
??? "BirthDate": "\/Date(501897600000)\/",
??? "LastModified": "\/Date(1292803200000)\/",
??? "Name": "James"
? }
]
在大多數情況下這是期望的結果,但是在某些場景下,將list中的第二項作為第一項的一個引用來輸出會是一個更好的解決方案。如果上面的Json現在被反序列化,返回的list會包含兩個完全分離的對象,它們具有相同的值。通過值來輸出引用也會在對象上導致循環引用的發生。
>PreserveReferencesHandling
?? string json2 = JsonConvert.SerializeObject(people, Formatting.Indented,
??????????????? new JsonSerializerSettings() { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
??????????? Console.WriteLine(json2);
輸出結果:
???????? ?[
????????????? {
??????????????? "$id": "1",
??????????????? "BirthDate": "\/Date(501897600000)\/",
??????????????? "LastModified": "\/Date(1292803200000)\/",
??????????????? "Name": "James"
????????????? },
????????????? {
??????????????? "$ref": "1"
????????????? }
??????????? ]?
????????? List<Person> deserializedPeople = JsonConvert.DeserializeObject<List<Person>>(json2,
??????????????? new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
??????????? Console.WriteLine(deserializedPeople.Count);// 2???????
??????????? Person p1 = deserializedPeople[0];
??????????? Person p2 = deserializedPeople[1];
??????????? Console.WriteLine(p1.Name);// James
??????????? Console.WriteLine(p2.Name);// James
??????????? bool equal = Object.ReferenceEquals(p1, p2);// true
在list中的第一個Person被序列化時增加了一個額外的對象Id,現在第二個Person對象僅僅是第一個的引用。
現在使用PreserveReferencesHandling后,在序列化時只創建了一個Person對象,list中包含它的兩個引用,原來我們叫作反射(mirroring) 。
>IsReference on JsonObjectAttribute, JsonArrayAttribute and JsonPropertyAttribute
? 在對象序列化器上設置PreserveReferencesHandling,將會改變所有對象被序列化和反序列化的方式。為了更加細致地控制對象和成員被序列化為一個引用,可以在JsonObjectAttribute, JsonArrayAttribute 和 JsonPropertyAttribute上使用IsReference 屬性.
在JsonObjectAttribute, JsonArrayAttribute 上設置IsReference 為true,意味著Json序列化器總是會序列這個類型為一個引用。在JsonPropertyAttribute上設置IsReference為true將只序列化這個屬性為一個引用。
?[JsonObject(IsReference = true)]
??? public class EmployeeReference
??? {
??????? public string Name { get; set; }
??????? public EmployeeReference Manager { get; set; }
??? }
測試:
?????????? List<EmployeeReference> empList = new List<EmployeeReference>();
??????????? empList.Add(empRef);
??????????? empList.Add(empRef);
??????????? string empRefJson = JsonConvert.SerializeObject(empList, Formatting.Indented);
??????????? Console.WriteLine(empRefJson);
輸出結果:
[
? {
??? "$id": "1",
??? "Name": "IsReference",
??? "Manager": null
? },
? {
??? "$ref": "1"
? }
]
>IReferenceResolver
要想定制引用的生成方式,可以繼承自IReferenceResolver接口來使用Json序列化器。
posted @ 2011-06-11 15:10 資源收集 閱讀(49) 評論(0)?編輯 Json.Net學習筆記(七) 序列化集合Json序列化器為序列化及反序列化集合對象提供了良好的支持.
->Serializing
?? 為了序列化一個集合---一個泛型的list,array,dictionary,或者自定義集合---簡單地調用序列化器,使用您想要進行序列化的集合對象作為參數,Json.Net會序列化集合以及所有它包含的值。
示例:
public class Product
??? {
??????? public string Name { get; set; }
??????? public decimal Price { get; set; }
??????? [JsonConverter(typeof(IsoDateTimeConverter))]
??????? public DateTime ExpiryDate { get; set; }
??? }
測試:
??????????? Product p1 = new Product()
??????????? {
??????????????? Name = "Product 1",
??????????????? Price = 99.95m,
??????????????? ExpiryDate = new DateTime(2010, 12, 19, 0, 0, 0, DateTimeKind.Utc)
??????????? };
??????????? Product p2 = new Product
??????????? {
??????????????? Name = "Product 2",
??????????????? Price = 12.50m,
??????????????? ExpiryDate = new DateTime(2011, 1, 1, 0, 0, 0, DateTimeKind.Utc)
??????????? };
??????????? List<Product> products = new List<Product>();
??????????? products.Add(p1);
??????????? products.Add(p2);
??????????? string json = JsonConvert.SerializeObject(products, Formatting.Indented);
??????????? Console.WriteLine(json);
輸出結果:
[
? {
??? "Name": "Product 1",
??? "Price": 99.95,
??? "ExpiryDate": "2010-12-19T00:00:00Z"
? },
? {
??? "Name": "Product 2",
??? "Price": 12.50,
??? "ExpiryDate": "2011-01-01T00:00:00Z"
? }
]
->Deserializing
? 為了反序列化Json到一個.Net集合中,只要指定一個您想要反序列化的集合類型就可以了,Json.Net支持多種類型的集合.
示例:
? ? string json2 = @"[
????????????????????????????? {
??????????????????????????????? ""Name"": ""Product 1"",
??????????????????????????????? ""ExpiryDate"": ""2010-12-19T00:00:00Z"",
??????????????????????????????? ""Price"": 99.95,
??????????????????????????????? ""Sizes"": null
????????????????????????????? },
????????????????????????????? {
??????????????????????????????? ""Name"": ""Product 2"",
??????????????????????????????? ""ExpiryDate"": ""2011-01-01T00:00:00Z"",
??????????????????????????????? ""Price"": 12.50,
??????????????????????????????? ""Sizes"": null
????????????????????????????? }
??????????????????????????? ]";
??????????? List<Product> productList = JsonConvert.DeserializeObject<List<Product>>(json2);
??????????? Console.WriteLine(productList.Count);//2
??????????? Product product1 = productList[0];
??????????? Console.WriteLine(product1.Name);//Product 1
->Deserializing Dictionaries
? 使用Json.Net你也可以反序列化一個Json對象到一個.Net的泛型Dictionary中.Json對象的屬性名和屬性值將會被添加到Dictionary中.
示例:
? ? ? ? ? ? string jsonDictionary = @"{""key1"":""value1"",""key2"":""value2""}";
??????????? Dictionary<string, string> dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonDictionary);
??????????? Console.WriteLine(dic.Count);//2
??????????? Console.WriteLine(dic["key1"]);//value1
Json.Net支持序列化回調方法,回調方法通過Json序列化器(JsonSerializer)可以用來操作一個對象,在它被序列化和反序列化之前或者之后.
OnSerializing?
OnSerialized?
OnDeserializing?
OnDeserialized
為了告訴序列化器在對象的序列化生命周期中哪個方法應該被調用,需要用適當的attribute(OnSerializingAttribute,?OnSerializedAttribute,?OnDeserializingAttribute,?OnDeserializedAttribute)來標記方法.
例如對象序列化的回調方法:
using Newtonsoft.Json;
using System.Runtime.Serialization;
?public class SerializationEventTestObject
??? {
??????? // This member is serialized and deserialized with no change.
??????? public int Member1 { get; set; }
??????? // The value of this field is set and reset during and?
??????? // after serialization.
??????? public string Member2 { get; set; }
??????? // This field is not serialized. The OnDeserializedAttribute?
??????? // is used to set the member value after serialization.
??????? [JsonIgnore]
??????? public string Member3 { get; set; }
??????? // This field is set to null, but populated after deserialization.
??????? public string Member4 { get; set; }
??????? public SerializationEventTestObject()
??????? {
??????????? Member1 = 11;
??????????? Member2 = "Hello World!";
??????????? Member3 = "This is a nonserialized value";
??????????? Member4 = null;
??????? }
??????? [OnSerializing]
??????? internal void OnSerializingMethod(StreamingContext context)
??????? {
??????????? Member2 = "This value went into the data file during serialization.";
??????? }
??????? [OnSerialized]
??????? internal void OnSerializedMethod(StreamingContext context)
??????? {
??????????? Member2 = "This value was reset after serialization.";
??????? }
??????? [OnDeserializing]
??????? internal void OnDeserializingMethod(StreamingContext context)
??????? {
??????????? Member3 = "This value was set during deserialization";
??????? }
??????? [OnDeserialized]
??????? internal void OnDeserializedMethod(StreamingContext context)
??????? {
??????????? Member4 = "This value was set after deserialization.";
??????? }
??? }
示例對象被序列化和反序列化:
?SerializationEventTestObject obj = new SerializationEventTestObject();
??????????? Console.WriteLine(obj.Member1);// 11
??????????? Console.WriteLine(obj.Member2);// Hello World!
??????????? Console.WriteLine(obj.Member3);// This is a nonserialized value
??????????? Console.WriteLine(obj.Member4);// null
??????????? string json = JsonConvert.SerializeObject(obj, Formatting.Indented);
??????????? Console.WriteLine(json);
??????????? //? "Member1": 11,
??????????? //? "Member2": "This value went into the data file during serialization.",
??????????? //? "Member4": null
??????????? //}
?
??????????? Console.WriteLine(obj.Member1);//11
??????????? Console.WriteLine(obj.Member2);// This value was reset after serialization.
??????????? Console.WriteLine(obj.Member3);// This is a nonserialized value
??????????? Console.WriteLine(obj.Member4);// null
??????????? obj = JsonConvert.DeserializeObject<SerializationEventTestObject>(json);
??????????? Console.WriteLine(obj.Member1);//11
??????????? Console.WriteLine(obj.Member2);// This value went into the data file during serialization.
??????????? Console.WriteLine(obj.Member3);// This value was set during deserialization
??????????? Console.WriteLine(obj.Member4);// This value was set after deserialization.
Attributes 可以用來控制Json.Net如何序列化和反序列化.Net對象。
>JsonObjectAttribute--標記在類上,用于控制該類如何被序列化為一個Json對象(JSON Object)
>JsonArrayAttribute--標記在集合上,用于控制該集合如何被序列化為一個Json集合(JSON Array)
>JsonPropertyAttribute--標記在字段和屬性上,用于控制它如何被序列化為一個Json對象中的屬性
>JsonConverterAttribute--標記在類或者字段和屬性上,用于序列化時指定Json轉換器(JsonConverter)
?和使用內置的Json.Net attributes一樣,當確定Json如何被序列化和反序列化時,Json.Net也查找DataContract和DataMember attributes。如果都存在,Json.Net 序列化特性將優先使用。
示例:
?? [JsonObject(MemberSerialization.OptOut)]
??? public class Person
??? {
??????? // "John Smith"
??????? [JsonProperty]
??????? public string Name { get; set; }
??????? // "2000-12-15T22:11:03"
??????? [JsonProperty]
??????? [JsonConverter(typeof(IsoDateTimeConverter))]
??????? public DateTime BirthDate { get; set; }
??????? // new Date(976918263055)
??????? [JsonProperty]
??????? [JsonConverter(typeof(JavaScriptDateTimeConverter))]
??????? public DateTime LastModified { get; set; }
??????? // not serialized
??????? public string Department { get; set; }
??? }
->JsonObjectAttribute
??這里的MemberSerialization標記指定成員序列化為opt-in(每一個成員都必須標記JsonProperty或者DataMember attribute才被序列化)或者opt-out(默認情況下,除了被標記為JsonIgnoreAttribute的所有成員都將被序列化,這是Json.Net 的默認行為)
? Json.Net把實現了IEnumerable接口的.Net類序列化為一個Json集合,用IEnumerable 的值來填充該集合。標記JsonPropertyAttribute來重寫此行為,并強制序列化器序列化該類的字段和屬性。
->JsonPropertyAttribute
? JsonPropertyAttribute有很多用途
??? 1.默認情況下,Json 屬性與.Net屬性有相同的名字,這個attribute允許自定義屬性名
??? 2.當member serialization 被設置成opt-in時,指定屬性應該被序列化
??? 3.在序列化和反序列化時包含非public屬性
->JsonIgnoreAttribute
? 從序列化中排除指定的字段或者屬性
->JsonConverterAttribute
? JsonConverterAttribute指定Json序列化器(JsonSerializer)用來轉換一個對象
? 這個特性可以用來標記類或者成員,當它用來標記類的時候,由attribute指定的JsonConverter將為類提供默認的序列化方法.當它用來標記字段或者屬性的時候,指定的JsonConverter將一直用于序列化該值。
? 使用JsonConverter的優先級順序為:先成員,后類,最后為傳給JsonSerializer的任何轉換器.
示例:
??? public class MemberConverterClass
??? {
??????? public DateTime DefaultConverter { get; set; }
??????? [JsonConverter(typeof(IsoDateTimeConverter))]
??????? public DateTime MemberConverter { get; set; }
??? }//注:這是一個JsonConverterAttribute 應用于屬性的例子
測試:
?DateTime date = Convert.ToDateTime("1970-01-01T00:00:00Z").ToUniversalTime();
??????????? MemberConverterClass c = new MemberConverterClass
??????????? {
??????????????? DefaultConverter = date,
??????????????? MemberConverter = date
??????????? };
??????????? string json = JsonConvert.SerializeObject(c, Formatting.Indented);
??????????? Console.WriteLine(json);
輸出結果:
{
? "DefaultConverter": "\/Date(0)\/",
? "MemberConverter": "1970-01-01T00:00:00Z"
} posted @ 2011-06-11 15:08 資源收集 閱讀(133) 評論(0)?編輯 Json.Net學習筆記(六) Json.Net中關于時間的序列化
DateTime類型在Json中表示是很難的。
問題來源于JSON spec?(Json規范)自身,沒有精確的語法。這個規范包括objects, arrays, strings, integers 和 floats,但是對于date是什么樣子的沒有定義準確的標準。
關于時間,Json.Net使用的默認格式與微軟:"\/Date(1198908717056)\/"相同,您可以從此外獲得更多信息.
DateTime JsonConverters
由于在Json中沒有關于時間的準確標準,當與其他系統進行互操作時就會有大量不同的時間格式。幸運的是,Json.Net為了處理讀寫自定義時間提供了一個解決方案:JsonConverters. JsonConverter是用來重寫一個類型如何被序列化的。
示例:?
public class LogEntry
??? {
??????? public string Details { get; set; }
??????? public DateTime LogDate { get; set; }
??? }
測試1:
?????? LogEntry logEntry = new LogEntry()
??????????? {
??????????????? LogDate = new DateTime(2010, 12, 19, 0, 0, 0, DateTimeKind.Utc),
??????????????? Details = "Application started."
??????????? };
??????????? string defaultJson = JsonConvert.SerializeObject(logEntry, Formatting.Indented);
??????????? Console.WriteLine(defaultJson);
輸出結果:
{
? "Details": "Application started.",
? "LogDate": "\/Date(1292716800000)\/"
}
測試2:
??? string javascriptJson = JsonConvert.SerializeObject(logEntry, Formatting.Indented, new JavaScriptDateTimeConverter());
???? Console.WriteLine(javascriptJson);
輸出結果:
{
? "Details": "Application started.",
? "LogDate": new Date(
??? 1292716800000
? )
}
測試3:
??????????? string isoJson = JsonConvert.SerializeObject(logEntry, Formatting.Indented, new IsoDateTimeConverter());
??????????? Console.WriteLine(isoJson);
輸出結果:
{
? "Details": "Application started.",
? "LogDate": "2010-12-19T00:00:00Z"
}
?簡單地,通過JsonConverter您可以使用Json.Net的序列化器
>JavaScriptDateTimeConverter
? JavaScriptDateTimeConverter類是來自于Json.Net的兩個DataTime Json轉換器之一,這個轉換器序列化一個DateTime類型為一個JavaScipt日期對象(https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date)
? new Date(1292716800000)
從技術上講,根據規范這是無效的數據格式,但是所有的瀏覽器、和一些Json的框架包括Json.Net都支持它。
>IsoDateTimeConverter
? IsoDateTimeConverter序列一個DateTime類型為一個ISO 8601格式的字符串.
? "2010-12-19T00:00:00Z"
IsoDateTimeConverter 類有一個屬性DateTimeFormat,用來更進一步的自定義字符串格式.
最后要注意的一件事是,所有被Json.Net返回的日期值都是UTC Time
posted @ 2011-06-11 15:08 資源收集 閱讀(109) 評論(0)?編輯 Json.Net學習筆記(三) Json與Xml之間的轉換Json.Net 支持 Json 與Xml之間的相互轉換.
轉換規則:
?1.元素保持不變
?2.屬性添加前綴@
?3.單個子文本結點直接作為元素結點的值,否則通過#text訪問
?4.XML聲明和處理指令以?為前綴
?5.字符數據(Character data)、注釋、whitespace 和significate whitespace結點分別通過#cdata-section,#comment,#whitespace and #significate-whitespace 訪問。
?6.同一級多個相同名字的結點作為一組,放到同一個集合中
?7.空元素為null
using Newtonsoft.Json;
測試:
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>
??????????????????????????? Hello World
??????????????????????????? </root>";
??????????? XmlDocument doc = new XmlDocument();
??????????? doc.LoadXml(xml);
?????????? //XML?to JSON
??????????? string jsonText = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.Indented);
??????????? Console.WriteLine(jsonText);
輸出結果:
{
? "?xml": {
??? "@version": "1.0",
??? "@standalone": "no"
? },
? "root": {
??? "person": [
????? {
??????? "@id": "1",
??????? "name": "Alan",
??????? "url": "http://www.google.com"
????? },
????? {
??????? "@id": "2",
??????? "name": "Louis",
??????? "url": "http://www.yahoo.com"
????? }
??? ],
??? "#text": "\r\n??????????????????????????? Hello World\r\n??????????????????????????? "
? }
}
?
??????????? //JSON to XML
?????????? ?XmlDocument docJson = (XmlDocument)JsonConvert.DeserializeXmlNode(jsonText);
??????????? Console.WriteLine(docJson.InnerXml);
為了手動讀寫Json對象,Json.Net提供了JsonReader 和 JsonWriter這兩個抽象類及其相應的派生類:
1.JsonTextReader 和 JsonTextWriter
用來讀寫Json對象的文本,JsonTextWriter 有大量設置去控制Json對象的格式。
測試:
??????????? //寫操作
??????????? StringBuilder sb = new StringBuilder();
??????????? StringWriter sw = new StringWriter(sb);
??????????? using (JsonWriter jsonWriter = new JsonTextWriter(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.WriteEndArray();
??????????????? jsonWriter.WriteEndObject();
??????????? }
??????????? Console.WriteLine(sb.ToString());
輸出結果:
{
? "CPU": "Intel",
? "PSU": "500W",
? "Drives": [
??? "DVD read/writer"
??? /*(broken)*/,
??? "500 gigabyte hard drive",
??? "200 gigabype hard drive"
? ]
}
????? //讀操作
???? TextReader txtReader = new StringReader(sb.ToString());
??????????? using (JsonReader jsonReader = new JsonTextReader(txtReader))
??????????? {
??????????????? string readResult = "{\n";
??????????????? while (jsonReader.Read())
??????????????? {
??????????????????? if (jsonReader.TokenType == JsonToken.PropertyName)
??????????????????? {
??????????????????????? readResult += (string)jsonReader.Value + ":";
??????????????????? }
??????????????????? else if (jsonReader.TokenType == JsonToken.String)
??????????????????? {
??????????????????????? readResult += (string)jsonReader.Value + "\n";
??????????????????? }
??????????????????? else if (jsonReader.TokenType == JsonToken.StartArray)
??????????????????? {
??????????????????????? readResult += "[\n";
??????????????????????? while (jsonReader.Read())
??????????????????????? {
??????????????????????????? if (jsonReader.TokenType == JsonToken.EndArray)
??????????????????????????? {
??????????????????????????????? readResult = readResult.Remove(readResult.Length - 2, 1);
??????????????????????????????? readResult += "]\n";
??????????????????????????????? break;
??????????????????????????? }
??????????????????????????? if (jsonReader.TokenType == JsonToken.String)
??????????????????????????????? readResult += (string)jsonReader.Value + ",\n";
??????????????????????????? else if (jsonReader.TokenType == JsonToken.Comment)
??????????????????????????????? readResult += "/*" + (string)jsonReader.Value + "*/,\n";
??????????????????????? }
??????????????????? }
??????????????? }
??????????????? readResult += "}\n";
??????????????? Console.WriteLine(readResult);
???????????? }
2.JTokenReader and JTokenWriter
JTokenReader and JTokenWriter是讀寫Linq to Json對象的,他們存在于Newtonsoft.Json.Linq名字空間中
???????? JObject o = new JObject(
??????????????????????? new JProperty("Name", "ZhangSan"),
??????????????????????? new JProperty("BirthDay", new DateTime(1985, 11, 27)));
??????????? JsonSerializer serializer = new JsonSerializer();
??????????? Person person = (Person)serializer.Deserialize(new JTokenReader(o), typeof(Person));
??????????? Console.WriteLine(person.Name);//輸出ZhangSan
using Newtonsoft.Json.Linq;
定義類:
??? public class Product
??? {
??????? public string Name { get; set; }
??????? public DateTime Expiry { get; set; }
??????? public decimal Price { get; set; }
??????? public string[] Sizes { get; set; }
??? }
測試:
??????????? Product product = new Product
??????????? {
??????????????? Name = "Apple",
??????????????? Expiry = new DateTime(2010, 12, 18),
??????????????? Price = 3.99M,
??????????????? Sizes = new string[] { "Small", "Medium", "Large" }
??????????? };
??????????? string serializedJson = JsonConvert.SerializeObject(product);
????????????JObject o = JObject.Parse(serializedJson);
??????????? string name = (string)o["Name"];
??????????? //Apple
??????????? JArray sizes = (JArray)o["Sizes"];
??????????? string smallest = (string)sizes[0];
??????????? Response.Write(name + "," + smallest + "<br/>");//輸出Small
??????????? //SelectToken
??????????? smallest = (string)o.SelectToken("Sizes[0]");
??????????? Response.Write(smallest + "<br/>");//輸出Small
??????????? //SelectToken with Linq
??????????? var sizeLen5 = o["Sizes"].Select(i => (string)i).Where(i => i.Length == 5).ToList<string>();
????????? ?foreach (var size in sizeLen5)
??????????? {
??????????????? Response.Write((string)size+ " <br/>");
??????????? };//輸出Small和Large
注:JArray表示一個Json集合,JObject表示一個Json對象。
posted @ 2011-06-11 15:03 資源收集 閱讀(117) 評論(0)?編輯 Json.Net?學習筆記(一)使用Newtonsoft.Json這是一個開源的Json.Net庫。
下載地址:http://json.codeplex.com/releases/view/50552。當前版本為 Release 8
從下載到的源代碼中獲取Newtonsoft.Json.Net20.dll,添加到自己的工程中。
using Newtonsoft.Json;
定義類:
?public class Message
??? {
??????? public string Address { get; set; }
??????? [JsonProperty(TypeNameHandling = TypeNameHandling.All)]
??????? public object Body { get; set; }
??? }
??? public class SearchDetails
??? {
??????? public string Query { get; set; }
??????? public string Language { get; set; }
??? }
測試:
?????????? Message message = new Message
??????????? {
??????????????? Address = "http://google.com",
??????????????? Body = new SearchDetails { Query = "Json.Net", Language = "en-us" }
??????????? };
??????????? string jsonMsg = JsonConvert.SerializeObject(message, Formatting.Indented);//Indented表示以縮進形式顯示結果
??????????? System.Diagnostics.Debug.Write(jsonMsg);
??????????? Message deserialized = JsonConvert.DeserializeObject<Message>(jsonMsg);
??????????? SearchDetails searchDetails = (SearchDetails)deserialized.Body;
??????????? Response.Write(searchDetails.Query + "," + searchDetails.Language + "<br/>");
Debug輸出結果格式:
{
? "Address": "http://google.com",
? "Body": {
??? "$type": "TestJsonSerialization.SearchDetails, TestJsonSerialization",
??? "Query": "Json.Net",
??? "Language": "en-us"
? }
}
注:1.JsonProperty標記字段或屬性,用來控制它作為一個Json對象的屬性序列化。
?????? 2.TypeNameHandling 用來為Json序列化指定類型名。它有幾個枚舉值:
| Member | Description |
|---|---|
| None | Do not include the .NET type name when serializing types.? |
| Objects | Include the .NET type name when serializing into a JSON object structure.? |
| Arrays | Include the .NET type name when serializing into a JSON array structure.? |
| Auto | Include the .NET type name when the type of the object being serialized is not the same as its declared type.? |
| All | Always include the .NET type name when serializing.? |
| 上一篇?在ASP.NET MVC 中獲取當前URL、controller、action(轉載) | 下一篇?ASP.NET-關于Container dataitem 與 eval方法介紹(轉帖) |
轉載于:https://www.cnblogs.com/wuyifu/p/3299784.html
總結
以上是生活随笔為你收集整理的Json.Net学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vmware克隆centos修改linu
- 下一篇: 柴犬多少钱啊?