我的代码结构如下。
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<Stats>
可变数据也在更新期间发送,这是一大块数据,我只想发送 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<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; }
}
关于c# - 类的自定义 Json 序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11934487/