类的自定义 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<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 是一个非常好的库,但我真的不知道如何正确使用它来获得我想要的东西。

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

有两种不同的方法可以解决您的问题。

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

如果您只有这两个类,并且它们很可能不会更改,则可以选择第二种方法来保持解决方案简单。

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

哦,知道了,重新阅读您的问题,我认为您可以序列化数据的投影。

您可以尝试以下操作:

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

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

原答案:

我认为你的类没有问题,你没有任何奇怪的循环引用,所以 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}

这对我来说看起来不错。

相关内容

  • 没有找到相关文章

最新更新