本文以一个简单的小例子,简述Json.Net的相关知识,仅供学习分享使用,如有不足之处,还请指正。
概述
Json.Net is a Popular high-performance JSON framework for .NET.
Json.Net是当前比较流行的高效的Json解析的.Net框架。主要支持序列化,反序列化,手动解析,Linq等功能,可谓是功能强大而使用简单。
- 使用方式:在项目中引入Newtonsoft.Json.dll文件即可里面的功能。
- 常见功能:序列化与反序列化
- 常用的类:JsonConvert,JsonSerializerSettings,JValue,JArray,JObject,Formatting,JTokenWriter,JToken @H_404_21@
效果图
具体如下图所示【序列化和反序列化】:
核心代码
序列化和反序列化的代码如下
1 public partial class JsonForm : Form 2 { 3 public JsonForm() 4 { 5 InitializeComponent(); 6 } 7 8 /// <summary> 9 /// 序列化对象 10 </summary> 11 <param name="sender"></param> 12 <param name="e"></param> 13 private void btnSerializeObject_Click(object sender,EventArgs e) 14 15 Person p = new Person() 16 { 17 Name = "Hexiang", 18 Birthday = DateTime.Parse(2017-02-20 14:30:00),1)"> 19 Gender = 男 20 love = Ball" 21 }; 22 string strjson = JsonConvert.SerializeObject(p,Formatting.Indented); 23 this.txtJson.Text = strjson; 24 25 26 27 序列化字典 28 29 30 31 void btnSerializeDictionary_Click( 32 33 Dictionary<string,int> dicPoints = new Dictionary<int>(){ 34 { James",9001 },1)"> 35 { Jo3474 36 { Jess11926 } 37 38 39 JsonConvert.SerializeObject(dicPoints,1)"> 40 41 42 43 44 45 46 序列化List 47 48 49 50 void btnSerializeList_Click( 51 52 List<string> lstGames = new List<string>() 53 54 Starcraft 55 Halo 56 Legend of Zelda 57 58 59 JsonConvert.SerializeObject(lstGames); 60 61 62 63 64 65 序列化到文件 66 67 68 69 void btnSerializetoFile_Click( 70 71 Person p = 72 73 Name = 74 Birthday = DateTime.Parse( 75 Gender = 76 love = 77 78 using (StreamWriter file = File.CreateText(@"d:\person.json)) 79 80 JsonSerializer serializer = JsonSerializer(); 81 serializer.Serialize(file,p); 82 } 83 84 85 86 序列化枚举 87 88 89 90 void btnSerializeEnum_Click( 91 92 List<StringComparison> stringComparisons = new List<StringComparison> 93 94 StringComparison.CurrentCulture,1)"> 95 StringComparison.Ordinal 96 }; 97 98 string jsonWithoutConverter = JsonConvert.SerializeObject(stringComparisons); 99 100 this.txtJson.Text = jsonWithoutConverter;//序列化出来是枚举所代表的整数值 101 102 103 string jsonWithConverter = JsonConvert.SerializeObject(stringComparisons,1)"> StringEnumConverter()); 104 this.txtJson.Text += \r\n; 105 this.txtJson.Text += jsonWithConverter;序列化出来是枚举所代表的文本值 106 ["CurrentCulture","Ordinal"] 107 108 List<StringComparison> newStringComparsions = JsonConvert.DeserializeObject<List<StringComparison>>( 109 jsonWithConverter,1)">110 111 112 113 114 序列化DataSet 115 116 117 118 void btnSerializeDataSet_Click(119 120 DataSet dataSet = new DataSet(dataSet); 121 dataSet.Namespace = NetFrameWork122 DataTable table = DataTable(); 123 DataColumn idColumn = new DataColumn(idtypeof(int)); 124 idColumn.AutoIncrement = true125 126 DataColumn itemColumn = item127 table.Columns.Add(idColumn); 128 table.Columns.Add(itemColumn); 129 dataSet.Tables.Add(table); 130 131 for (int i = 0; i < 2; i++) 132 133 DaTarow newRow = table.NewRow(); 134 newRow["] = item " + i; 135 table.Rows.Add(newRow); 136 137 138 dataSet.AcceptChanges(); 139 140 string json = JsonConvert.SerializeObject(dataSet,1)">141 json; 142 143 144 145 序列化JRaw 146 147 148 149 void btnSerializeRaw_Click(150 151 JavaScriptSettings settings = JavaScriptSettings 152 153 OnLoadFunction = new JRaw(OnLoad154 OnUnloadFunction = function(e) { alert(e); }155 156 157 JsonConvert.SerializeObject(settings,1)">158 159 160 161 162 163 164 反序列化List 165 166 167 168 void btnDeserializeList_Click(169 170 string json = ['Starcraft','Halo','Legend of Zelda']171 List<string> videogames = JsonConvert.DeserializeObject<List<string>>(json); 172 this.txtJson.Text = string.Join(173 174 175 176 反序列化字典 177 178 179 180 void btnDeserializeDictionary_Click(181 182 { 183 'href': '/account/login.aspx',1)">184 'target': '_blank' 185 }186 187 Dictionary<string> dicAttributes = JsonConvert.DeserializeObject<Dictionary<188 189 this.txtJson.Text = dicAttributes[href]; 190 191 this.txtJson.Text += dicAttributes[target192 193 194 195 196 197 反序列化匿名类 198 199 200 201 void btnDeserializeAnaymous_Click(202 203 var deFinition = new { Name = "" }; 204 205 string json1 = {'Name':'James'}206 var customer1 = JsonConvert.DeserializeAnonymousType(json1,deFinition); 207 customer1.Name; 208 209 210 string json2 = {'Name':'Mike'}211 var customer2 = JsonConvert.DeserializeAnonymousType(json2,1)">212 this.txtJson.Text += customer2.Name; 213 214 215 216 217 反序列化DataSet 218 219 220 221 void btnDeserializeDataSet_Click(222 223 224 'Table1': [ 225 { 226 'id': 0,1)">227 'item': 'item 0' 228 },1)">229 230 'id': 1,1)">231 'item': 'item 1' 232 } 233 ] 234 }235 236 DataSet dataSet = JsonConvert.DeserializeObject<DataSet>237 238 DataTable dataTable = dataSet.Tables[Table1239 dataTable.Rows.Count.ToString(); 240 241 242 foreach (DaTarow row in dataTable.Rows) 243 244 245 this.txtJson.Text += (row["] + - " + row[]); 246 247 248 249 250 251 从文件反序列化 252 253 254 255 void btnDeserializefrmFile_Click(256 257 using (StreamReader file = File.OpenText(258 259 JsonSerializer serializer = 260 Person p = (Person)serializer.Deserialize(file,1)">typeof(Person)); 261 p.Name; 262 263 264 265 266 反序列化带构造函数人类 267 268 269 270 void btnDeserializeConstructor_Click(271 272 {'Url':'http://www.google.com'}273 274 直接序列化会报错,需要设置JsonSerializerSettings中ConstructorHandling才可以。 275 Website website = JsonConvert.DeserializeObject<Website>(json,1)"> JsonSerializerSettings 276 277 ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor 278 }); 279 280 website.Url; 281 282 283 284 285 反序列化对象,如果有构造函数中,创建对象,则用Json的进行替换 286 287 288 289 void btnDeserializeObjectCreation_Click(290 291 // 292 293 'Name': 'James',1)">294 'Offices': [ 295 'Auckland',1)">296 'Wellington',1)">297 'Christchurch' 298 ] 299 300 301 Userviewmodel model1 = JsonConvert.DeserializeObject<Userviewmodel>302 303 默认会重复 304 305 306 每次从Json中创建新的对象 307 Userviewmodel model2 = JsonConvert.DeserializeObject<Userviewmodel>(json,1)">308 309 ObjectCreationHandling = ObjectCreationHandling.Replace 310 311 312 313 314 315 316 317 序列化默认值处理,没有赋值的则不序列化出来 318 319 320 321 void btnSerializeDefautValue_Click(322 323 Person person = Person(); 324 325 string jsonIncludeDefaultValues = JsonConvert.SerializeObject(person,1)">326 327 this.txtJson.Text=(jsonIncludeDefaultValues);默认的序列化,带不赋值的属性 328 329 330 331 string jsonIgnoreDefaultValues = JsonConvert.SerializeObject(person,Formatting.Indented,1)">332 333 DefaultValueHandling = DefaultValueHandling.Ignore 去掉不赋值的属性 334 335 336 this.txtJson.Text+=(jsonIgnoreDefaultValues); 337 338 339 340 如果实体类中没有对应属性,则如何处理 341 342 343 344 void btnDeserializeMissingMember_Click(345 346 347 'FullName': 'Dan Deleted',1)">348 'Deleted': true,1)">349 'DeletedDate': '2013-01-20T00:00:00' 350 351 352 try 353 354 JsonConvert.DeserializeObject<Account>(json,1)">355 { 356 MissingMemberHandling = MissingMemberHandling.Error 要么忽略,要么报错 357 }); 358 359 catch (JsonSerializationException ex) 360 361 this.txtJson.Text=(ex.Message); 362 Could not find member 'DeletedDate' on object of type 'Account'. Path 'DeletedDate',line 4,position 23. 363 364 365 366 367 序列化时Null值的处理 368 369 370 371 void btnSerializeNull_Click(372 373 Person person = Person 374 375 Name = Nigal Newborn376 377 378 默认的序列化 379 string jsonIncludeNullValues =380 381 (jsonIncludeNullValues); 382 383 384 去掉Null值的序列化 385 string jsonIgnoreNullValues = JsonConvert.SerializeObject(person,1)">386 387 NullValueHandling = NullValueHandling.Ignore 可以忽略,可以包含 388 389 390 (jsonIgnoreNullValues); 391 392 393 394 395 序列化日期格式 396 397 398 399 void btnSerializeDateTime_Click(400 401 DateTime mayanEndOfTheWorld = new DateTime(2012,1)">12,1)">21402 403 string jsonIsoDate = JsonConvert.SerializeObject(mayanEndOfTheWorld); 404 405 (jsonIsoDate); 406 407 408 string jsonMsDate = JsonConvert.SerializeObject(mayanEndOfTheWorld,1)">409 410 DateFormatHandling = DateFormatHandling.MicrosoftDateFormat 411 412 413 (jsonMsDate); 414 "\/Date(1356044400000+0100)\/" 415 416 string json = JsonConvert.SerializeObject(mayanEndOfTheWorld,1)">417 418 DateFormatString = yyyy-MM-dd419 Formatting = Formatting.Indented 420 421 422 423 424 void btnSerializeDateZone_Click(425 426 Flight flight = Flight 427 428 Destination = dubai429 DepartureDate = 2013,1)">1,1)">21,1)">0,1)">0430 DepartureDateUtc = 431 DepartureDateLocal = 432 Duration = TimeSpan.FromHours(5.5433 434 435 string jsonWithroundtripTimeZone = JsonConvert.SerializeObject(flight,1)">436 437 DateTimeZoneHandling = DateTimeZoneHandling.roundtripKind 438 439 440 (jsonWithroundtripTimeZone); 441 442 string jsonWithLocalTimeZone = JsonConvert.SerializeObject(flight,1)">443 444 DateTimeZoneHandling = DateTimeZoneHandling.Local 445 446 447 (jsonWithLocalTimeZone); 448 449 450 string jsonWithUtcTimeZone = JsonConvert.SerializeObject(flight,1)">451 452 DateTimeZoneHandling = DateTimeZoneHandling.Utc 453 454 455 (jsonWithUtcTimeZone); 456 457 458 string jsonWithUnspecifiedTimeZone = JsonConvert.SerializeObject(flight,1)">459 460 DateTimeZoneHandling = DateTimeZoneHandling.Unspecified 461 462 463 (jsonWithUnspecifiedTimeZone); 464 465 466 467 void btnSerializeDataContract_Click(468 469 CFile file = CFile 470 471 Id = Guid.NewGuid(),1)">472 Name = ImportantLegalDocuments.docx473 Size = 50 * 1024 474 475 476 JsonConvert.SerializeObject(file,1)">477 478 479 480 481 482 序列化默认设置 483 484 485 486 void btnSerializeDefaultSetting_Click(487 488 settings will automatically be used by JsonConvert.SerializeObject/DeserializeObject 489 JsonConvert.DefaultSettings = () => 490 491 Formatting = Formatting.Indented,1)">492 ContractResolver = CamelCasePropertyNamesContractResolver() 493 494 495 Person s = 496 497 Name = Eric498 Birthday = 1980,1)">4,1)">20,1)">499 Gender = 500 love = Web Dude501 502 503 JsonConvert.SerializeObject(s); 504 505 506 507 508 序列化Immutable 509 510 511 512 void btnSerializeImmutable_Click(513 514 ImmutableList<string> l = ImmutableList.Createrange(new List<string> 515 { 516 "One",1)">517 "II",1)">518 "3" 519 }); 520 521 string json = JsonConvert.SerializeObject(l,Formatting.Indented); 522 523 524 525 526 序列化JsonProperty 527 528 529 530 void btnSerializeJsonProperty_Click(531 532 Videogame starcraft = Videogame 533 534 Name = 535 ReleaseDate = 1998,1)">1536 537 538 JsonConvert.SerializeObject(starcraft,1)">539 540 541 542 543 544 序列化排序,值越小,月靠前,默认是0 545 546 547 548 void btnSerializeOrder_Click(549 550 Account0 account = Account0 551 552 FullName = Aaron Account553 EmailAddress = [email protected]554 Deleted = 555 DeletedDate = 25556 UpdatedDate = 557 CreatedDate = 2010,1)">10,1)">558 559 560 JsonConvert.SerializeObject(account,1)">561 562 563 564 565 566 void btnSerializeJsonConstructor_Click(567 568 569 ""UserName"": ""domain\\username"",1)">570 ""Enabled"": true 571 572 573 User user = JsonConvert.DeserializeObject<User>574 575 (user.UserName); 576 577 578 579 void btnSerializeJsonIgnore_Click(580 581 Account1 account = Account1 582 583 FullName = Joe User584 EmailAddress = [email protected]585 PasswordHash = VHdlZXQgJ1F1aWNrc2lsdmVyJyB0byBASmFtZXNOSw==586 587 588 JsonConvert.SerializeObject(account); 589 590 591 592 593 其他功能 594 595 596 597 void btnOtherFunction_Click(598 599 JsonForm1 jsonOther = JsonForm1(); 600 jsonOther.ShowDialog(); 601 602 }
其他功能
具体如下图所示【其他功能】:
JsonForm1 : Form JsonForm1() 手动创建Json void btnCreateJsonManually_Click( 15 JArray array = JArray(); 16 array.Add(Manual text 17 array.Add(2000,1)">5,1)">23 18 19 JObject o = JObject(); 20 o[MyArray"] = array; 21 o.ToString(); 24 25 26 列表创建Json 31 32 void btnCollectionjson_Click( 33 34 JObject o = JObject() 35 cpuIntel 37 { Memory32 38 39 Drives JArray 40 { 41 DVD 42 SSD } 44 45 46 47 48 49 void btnCreateJsonByDynamic_Click( 52 dynamic product = 53 product.ProductName = Elbow Grease 54 product.Enabled = 55 product.Price = 4.90m 56 product.StockCount = 9000 57 product.StockValue = 44100 58 product.Tags = new JArray(RealOnSale product.ToString(); 61 62 63 从JTokenWriter创建Json 68 void btnJTokenWriter_Click( 69 70 JTokenWriter writer = JTokenWriter(); 71 writer.WriteStartObject(); 72 writer.WritePropertyName(name1 73 writer.WriteValue(value1 74 writer.WritePropertyName(name2 75 writer.WriteStartArray(); 76 writer.WriteValue( 77 writer.WriteValue(2 78 writer.WriteEndarray(); writer.WriteEndobject(); 80 81 JObject o = (JObject)writer.Token; 82 83 84 85 从对象创建Json 90 91 void btnCreateJsonFromObject_Click( 92 93 JValue i = (JValue)JToken.FromObject(12345 94 Console.WriteLine(i.Type); 96 Integer 97 Console.WriteLine(i.ToString()); 12345 100 JValue s = (JValue)JToken.FromObject(A string102 Console.WriteLine(s.Type); String 104 Console.WriteLine(s.ToString()); A string 106 107 Computer computer = Computer 108 109 cpu = 110 Memory = 111 Drives = string> 112 113 114 115 116 117 118 JObject o = (JObject)JToken.FromObject(computer); 119 120 Console.WriteLine(o.ToString()); 121 122 "cpu": "Intel",1)">123 "Memory": 32,1)">124 "Drives": [ 125 "DVD",1)">126 "SSD" 127 ] 128 } 129 130 JArray a = (JArray)JToken.FromObject(computer.Drives); 131 Console.WriteLine(a.ToString()); 133 [ 134 "DVD",1)">135 "SSD" 136 ] 137 138 139 140 从匿名对象创建 141 142 143 144 void btnCreateFromAnaymous_Click(145 146 List<Post> posts = new List<Post> 147 148 Post 149 150 Title = Episode VII151 Description = Episode VII production152 Categories = 153 154 episode-vii155 movie156 },1)">157 Link = episode-vii-production.aspx158 159 161 JObject o = JObject.FromObject(new 162 163 channel = 164 165 title = Star Wars166 link = http://www.starwars.com167 description = Star Wars blog.168 item = 169 from p posts 170 orderby p.Title 171 select 172 { 173 title = p.Title,1)">174 description = p.Description,1)">175 link = p.Link,1)">176 category = p.Categories 177 } 178 179 180 181 o.ToString(); 182 183 184 185 186 Parse 187 188 189 190 void btnJArrayParse_Click(191 192 [ 193 'Small',1)">194 'Medium',1)">195 'Large' 196 ]197 198 JArray a = JArray.Parse(json); 199 200 a.ToString(); 201 202 203 json = 204 cpu: 'Intel',1)">205 Drives: [ 206 'DVD read/writer',1)">207 '500 gigabyte hard drive' 208 209 210 211 JObject o = JObject.Parse(json); 212 213 214 215 JToken t1 = JToken.Parse({}216 217 Console.WriteLine(t1.Type); 218 Object 219 220 JToken t2 = JToken.Parse([]221 Console.WriteLine(t2.Type); Array 224 225 JToken t3 = JToken.Parse(null226 227 Console.WriteLine(t3.Type); 228 Null 229 230 JToken t4 = JToken.Parse('A string!'231 232 Console.WriteLine(t4.Type); 233 234 236 void btnDeserializeJsonLinq_Click(237 238 239 { 240 'Title': 'Json.NET is awesome!',1)">241 'Author': { 242 'Name': 'James Newton-King',1)">243 'Twitter': '@JamesNK',1)">244 'Picture': '/jamesnk.png' 245 246 'Date': '2013-01-23T19:30:00',1)">247 'BodyHtml': '<h3>Title!</h3>\r\n<p>Content!</p>' 248 } 249 ]250 251 JArray blogPostArray =252 253 IList<BlogPost> blogPosts = blogPostArray.Select(p => BlogPost 254 255 Title = (string)p[Title],1)">256 AuthorName = (Author"][Name257 AuthorTwitter = (Twitter258 PostedDate = (DateTime)p[Date259 Body = HttpUtility.HtmlDecode((BodyHtml]) 260 }).ToList(); 261 262 this.txtJson.Text=(blogPosts[].Body); 263 264 265 266 void btnSerializeJson_Click(267 268 IList<BlogPost> blogPosts = new List<BlogPost> 269 { 270 272 Title = Json.NET is awesome!273 AuthorName = James Newton-King274 AuthorTwitter = JamesNK275 PostedDate = 23,1)">19,1)">30,1)">276 Body = <h3>Title!</h3> 277 <p>Content!</p>279 }; 280 281 JArray blogPostsArray = JArray( 282 blogPosts.Select(p => JObject 283 284 { 285 286 287 288 { 289 { 291 },1)">292 { 293 },1)">294 { 295 }) 296 ); 297 298 (blogPostsArray.ToString()); 299 300 301 302 303 修改Json 304 305 306 307 void btnModifyJson_Click(309 310 'channel': { 311 'title': 'Star Wars',1)">312 'link': 'http://www.starwars.com',1)">313 'description': 'Star Wars blog.',1)">314 'obsolete': 'Obsolete value',1)">315 'item': [] 316 } 317 318 319 JObject RSS =320 321 JObject channel = (JObject)RSS[channel322 323 channel[title"] = ((string)channel[]).toupper(); 324 channel[description325 326 channel.Property(obsolete).Remove(); 327 328 channel.Property(").AddAfterSelf(new JProperty(newNew value329 330 JArray item = (JArray)channel[331 item.Add(Item 1332 item.Add(Item 2333 334 RSS.ToString(); 335 336 337 338 合并Json 342 void btnMergeJson_Click(343 344 JObject o1 = JObject.Parse(345 'FirstName': 'John',1)">346 'LastName': 'Smith',1)"> 'Enabled': false,1)"> 'Roles': [ 'User' ] 350 JObject o2 = JObject.Parse(351 'Enabled': true,1)">352 'Roles': [ 'User','Admin' ] 353 354 355 o1.Merge(o2,1)"> JsonMergeSettings 356 357 union array values together to avoid duplicates 358 MergeArrayHandling = MergeArrayHandling.Union 359 360 361 o1.ToString(); 362 363 364 365 查询Json 369 void btnQueryJson_Click(370 371 372 373 'title': 'James Newton-King',1)">374 'link': 'http://james.newtonking.com',1)">375 'description': 'James Newton-King\'s blog.',1)">376 'item': [ 377 { 378 'title': 'Json.NET 1.3 + New license + Now on CodePlex',1)">379 'description': 'Annoucing the release of Json.NET 1.3,the MIT license and the source on CodePlex',1)">380 'link': 'http://james.newtonking.com/projects/json-net.aspx',1)">381 'category': [ 382 'Json.NET',1)">383 'CodePlex' 384 ] 385 },1)">386 { 387 'title': 'LINQ to JSON beta',1)">388 'description': 'Annoucing LINQ to JSON',1)">389 390 391 392 'LINQ' 393 394 } 395 ] 396 397 398 399 JObject RSS =400 401 string RSSTitle = (string)RSS[403 Console.WriteLine(RSSTitle); 404 James Newton-King 405 406 string itemTitle = (0][407 408 Console.WriteLine(itemTitle); 409 Json.NET 1.3 + New license + Now on CodePlex 410 411 JArray categories = (JArray)RSS[category413 Console.WriteLine(categories); "Json.NET",1)"> "CodePlex" 417 418 419 string[] categoriesText = categories.Select(c => (string)c).ToArray(); 420 421 Console.WriteLine(422 Json.NET,CodePlex 423 424 425 void btnQueryWithLinq_Click(426 427 428 429 430 431 432 433 434 435 436 437 'category': [ 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 455 JObject RSS =456 457 var postTitles = 458 in RSS[] 459 select (460 461 foreach (var item postTitles) 462 463 Console.WriteLine(item); 464 465 LINQ to JSON beta 466 Json.NET 1.3 + New license + Now on CodePlex 467 468 var categories = 469 from c "].Children()["].Values< group c by c 471 into g 472 g.Count() descending 473 new { Category = g.Key,Count = g.Count() }; 474 475 var c categories) 476 477 Console.WriteLine(c.Category + - Count: c.Count); 478 479 Json.NET - Count: 2 480 LINQ - Count: 1 481 CodePlex - Count: 1 482 483 484 void btnjsonToXml_Click(485 486 487 '@Id': 1,1)">488 'Email': '[email protected]',1)">489 'Active': true,1)">490 'CreatedDate': '2013-01-20T00:00:00Z',1)">491 'Roles': [ 492 'User',1)">493 'Admin' 494 ],1)">495 'Team': { 496 '@Id': 2,1)">497 'Name': 'Software Developers',1)">498 'Description': 'Creators of fine software products and services.' 499 500 501 502 XNode node = JsonConvert.DeserializeXNode(json,1)">Root503 (node.ToString()); 505 506 507 508 void btnXmlToJson_Click(509 510 string xml = <?xml version='1.0' standalone='no'?> 511 <root> 512 <person id='1'> 513 <name>Alan</name> 514 <url>http://www.google.com</url> 515 </person> 516 <person id='2'> 517 <name>Louis</name> 518 <url>http://www.yahoo.com</url> 519 </person> 520 </root>521 522 XmlDocument doc = XmlDocument(); doc.LoadXml(xml); 525 JsonConvert.SerializeXmlNode(doc); 526 527 json; 528 529 }
备注:
关于Json的功能有很多,这里只是列举了一些基本的例子,其他的功能需要自己在用到的时候去查阅相关文档了。
关于使用说明文档可以去官网【http://www.newtonsoft.com/json】查看。Samples实例的网址如下:http://www.newtonsoft.com/json/help/html/Samples.htm
--------------------------------------------------------------------------------
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。