自定义Json序列化类

我的代码结构如下。

public class Stats { public string URL { get; set; } public string Status { get; set; } public string Title { get; set; } public string Description { get; set; } public int Length { get; set; } } 

  public class UrlStats { public string URL { get; set; } public int TotalPagesFound { get; set; } public List TotalPages { get; set; } public int TotalTitleTags { get; set; } public List TotalTitles { get; set; } public int NoDuplicateTitleTags { get; set; } public List DuplicateTitles { get; set; } public int NoOverlengthTitleTags { get; set; } public List OverlengthTitles { get; set; } } 

基本上我正在扫描网站上的标题,如标题标签,重复标题等。

我正在使用JQuery并对web服务进行AJAX调用并在流程运行时检索url统计数据,以显示迄今为止收集的用户url统计信息,因为扫描大型网站需要相当长的时间。 所以在每5秒后我从服务器检索统计数据。 现在问题是我需要在扫描处理完成时发送的所有List变量数据,而不是在更新期间。 正在发生的事情现在List变量数据也在更新过程中发送,这是大块数据,我想只发送显示进程更新所需的int类型变量。

从在互联网上搜索我找不到任何有用的解决我的问题,我发现Json.NET是非常好的库,但我真的不知道如何正确使用它来得到我想要的。

基本上我正在寻找在运行时根据其数据类型序列化属性,如果可能的话。

您的问题有两种不同的方法。

如果要更频繁地更改类,则应该选择第一个,因为第一种方法可以防止您忘记序列化新添加的属性。 此外,如果您想要以相同的方式添加要序列化的另一个类,则它更具可重用性。

如果您只有这两个类,而且最有可能的是它们不会改变,您可以选择第二种方法来保持解决方案的简单性。

1.使用自定义转换器选择所有int属性

第一种方法是使用自定义JsonConverter ,它通过仅包含类型为int属性来序列化类或结构。 代码可能如下所示:

 class IntPropertyConverter : JsonConverter { public override bool CanConvert(Type objectType) { // this converter can be applied to any type return true; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // we currently support only writing of JSON throw new NotImplementedException(); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) { serializer.Serialize(writer, null); return; } // find all properties with type 'int' var properties = value.GetType().GetProperties().Where(p => p.PropertyType == typeof(int)); writer.WriteStartObject(); foreach (var property in properties) { // write property name writer.WritePropertyName(property.Name); // let the serializer serialize the value itself // (so this converter will work with any other type, not just int) serializer.Serialize(writer, property.GetValue(value, null)); } writer.WriteEndObject(); } } 

然后你必须使用JsonConverterAttribute来装饰你的类:

 [JsonConverter(typeof(IntPropertyConverter))] public class UrlStats { // ... } 

免责声明:此代码仅经过大致测试。


2.单独选择属性

第二个解决方案看起来更简单:您可以使用JsonIgnoreAttribute来装饰要排除的序列化属性。 或者,您可以通过明确包含要序列化的属性,从“黑名单”切换到“白名单”。 这是一些示例代码:

黑名单:(我已重新排序属性以获得更好的概述)

 [JsonObject(MemberSerialization.OptOut)] // this is default and can be omitted public class UrlStats { [JsonIgnore] public string URL { get; set; } [JsonIgnore] public List TotalPages { get; set; } [JsonIgnore] public List TotalTitles { get; set; } [JsonIgnore] public List DuplicateTitles { get; set; } [JsonIgnore] public List OverlengthTitles { get; set; } public int TotalPagesFound { get; set; } public int TotalTitleTags { get; set; } public int NoDuplicateTitleTags { get; set; } public int NoOverlengthTitleTags { get; set; } } 

白名单:(也重新订购)

 [JsonObject(MemberSerialization.OptIn)] // this is important! public class UrlStats { public string URL { get; set; } public List TotalPages { get; set; } public List TotalTitles { get; set; } public List DuplicateTitles { get; set; } public List OverlengthTitles { get; set; } [JsonProperty] public int TotalPagesFound { get; set; } [JsonProperty] public int TotalTitleTags { get; set; } [JsonProperty] public int NoDuplicateTitleTags { get; set; } [JsonProperty] public int NoOverlengthTitleTags { get; set; } } 

哦得到它,重新阅读你的问题我认为你可以序列化你的数据投影。

您可以尝试以下方法:

 var json = JsonConvert.SerializeObject(new { u.TotalPagesFound, u.TotalTitleTags, u.NoDuplicateTitleTags, u.NoOverlengthTitleTags } ); 

这将仅转换为JSON类的int属性。 这是最简单的方法,它与你class级的结构有关。 如果您想要更通用的东西,则需要实现自定义转换器。

原始答案:

我认为你的类没有问题,你没有像循环引用那样奇怪的东西,所以Json.NET应该没有序列化你的类的问题。 所以去抓Json.NET然后你可以尝试以下

 // create new instance of your url stat class var u = new UrlStats() { URL = "a.com", TotalPages = new List() { new Stats() { URL = "b.com", Status = "xxxx" } } }; // seralize! var json = JsonConvert.SerializeObject(u); Console.Write(json); 

我用这种方法得到的是这样的:

 {"URL":"a.com","TotalPagesFound":0,"TotalPages":[{"URL":"b.com","Status":"xxxx","Title":null,"Description":null,"Length":0}],"TotalTitleTags":0,"TotalTitles":null,"NoDuplicateTitleTags":0,"DuplicateTitles":null,"NoOverlengthTitleTags":0,"OverlengthTitles":null} 

对我来说这看起来很好。