我的代码结构如下。
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<Stats> TotalPages { get; set; }
public int TotalTitleTags { get; set; }
public List<Stats> TotalTitles { get; set; }
public int NoDuplicateTitleTags { get; set; }
public List<Stats> DuplicateTitles { get; set; }
public int NoOverlengthTitleTags { get; set; }
public List<Stats> OverlengthTitles { get; set; }
}
基本上我正在网站上搜索标题标签,重复标题等统计信息。
我正在使用JQuery并对web服务进行AJAX调用,并在流程运行时检索url统计信息,以显示远远收集的用户url统计信息,因为扫描大型网站需要相当长的时间。所以在每5秒后我从服务器检索统计数据。现在问题是我需要在扫描处理完成时发送的所有List变量数据,而不是在更新期间。现在发生了什么List<Stats>
变量数据也在更新过程中发送,这是大块数据,我只想发送显示进程更新所需的int
类型变量。
从网上搜索我找不到任何有用的解决我的问题,我发现Json.NET是非常好的库,但我真的不知道如何正确使用它来得到我想要的。
基本上我正在寻找在运行时根据其数据类型序列化属性,如果可能的话。
答案 0 :(得分:28)
您的问题有两种不同的方法。
如果您要更频繁地更改类,则应该选择第一个,因为第一种方法可以防止您忘记序列化新添加的属性。此外,如果您想以相同的方式添加要序列化的另一个类,则可以重复使用它。
如果您只有这两个课程而且他们最不可能改变,您可以选择第二种方法来保持您的解决方案简单。
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
{
// ...
}
免责声明:此代码仅进行了非常粗略的测试。
第二个解决方案看起来更简单:您可以使用JsonIgnoreAttribute
来装饰要排除的序列化属性。或者,您可以切换&#34;黑名单&#34;到&#34;白名单&#34;通过显式包含要序列化的属性。以下是一些示例代码:
黑名单(我已对这些属性重新排序以获得更好的概述)
[JsonObject(MemberSerialization.OptOut)] // this is default and can be omitted
public class UrlStats
{
[JsonIgnore] public string URL { get; set; }
[JsonIgnore] public List<Stats> TotalPages { get; set; }
[JsonIgnore] public List<Stats> TotalTitles { get; set; }
[JsonIgnore] public List<Stats> DuplicateTitles { get; set; }
[JsonIgnore] public List<Stats> 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<Stats> TotalPages { get; set; }
public List<Stats> TotalTitles { get; set; }
public List<Stats> DuplicateTitles { get; set; }
public List<Stats> 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; }
}
答案 1 :(得分:2)
哦得到它,重新阅读你的问题我认为你可以序列化你的数据投影。
您可以尝试以下操作:
var json = JsonConvert.SerializeObject(new { u.TotalPagesFound, u.TotalTitleTags, u.NoDuplicateTitleTags, u.NoOverlengthTitleTags } );
这将只转换为JSON类的int属性。这是最简单的方法,它与你班级的结构有关。如果你想要更通用的东西,你需要实现一个自定义转换器。
原始答案:
我认为你的类没有问题,你没有像循环引用那样奇怪的东西,所以Json.NET应该没有序列化你的类的问题。所以去抓Json.NET然后你可以尝试以下
// create new instance of your url stat class
var u = new UrlStats() { URL = "a.com", TotalPages = new List<Stats>() { 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}
这对我来说就像是个好朋友。