Json.Net學習筆記


導讀: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"": ……
Json.Net 學習 筆記(十四) JSON的部分序列化

通常當用到大的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/

 
posted @ 2011-06-11 15:14 資源收集 閱讀(44) 評論(0) 編輯
 
 
Json.Net 學習 筆記(十三) 縮小序列化Json的大小
當序列化.Net對象為Json對象時經常會遇到的一個問題是:最終的Json包含大量多余的屬性和屬性值。這個問題在返回Json到客戶端時顯得特別重要。Json越大意味着需要更大的帶寬,使網速變得更慢。

為了解決多余的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
            // }

 
posted @ 2011-06-11 15:13 資源收集 閱讀(81) 評論(0) 編輯
 
 
Json.Net 學習 筆記(十二) 協議解析

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"
  ]

 
posted @ 2011-06-11 15:12 資源收集 閱讀(53) 評論(0) 編輯
 
 
Json.Net 學習 筆記(十一) CustomCreationConverter

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

 
posted @ 2011-06-11 15:11 資源收集 閱讀(28) 評論(0) 編輯
 
 
Json.Net 學習 筆記(九) 異常處理

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

 
posted @ 2011-06-11 15:09 資源收集 閱讀(73) 評論(0) 編輯
 
 
Json.Net 學習 筆記(八) 序列化的回調方法

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.

 
posted @ 2011-06-11 15:09 資源收集 閱讀(39) 評論(0) 編輯
 
 
Json.Net 學習 筆記(五) 自定義Json序列化特性

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);

 
posted @ 2011-06-11 15:04 資源收集 閱讀(68) 評論(0) 編輯
 
 
Json.Net 學習 筆記(四) Json對象的讀寫

為了手動讀寫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

 
posted @ 2011-06-11 15:04 資源收集 閱讀(167) 評論(0) 編輯
 
 
Json.Net   學習 筆記(二) Linq to Json

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. 
總結:{ "Address": "http://google.com", "Body": { "$type": "TestJsonSerialization.SearchDetails, TestJsonSerialization", "Query": "Json.Net", "Language": "en-us" }}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM