C# 类的自定义Json序列化

C# 类的自定义Json序列化,c#,json,json.net,C#,Json,Json.net,我的代码结构如下 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 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; }
}

公共类UrlStats
{
公共字符串URL{get;set;}
公共int TotalPagesFound{get;set;}
公共列表TotalPages{get;set;}
公共整数TotalTitleTags{get;set;}
公共列表TotalTitles{get;set;}
public int noduplicateTileTags{get;set;}
公共列表标题{get;set;}
public int NoOverlengthTitleTags{get;set;}
公共列表超长标题{get;set;}
}
基本上,我正在扫描一个网站的统计数据,如标题标签,重复标题等

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

通过在互联网上搜索,我找不到任何有用的方法来解决我的问题,我发现Json.NET是一个非常好的库,但我真的不知道如何正确地使用它来获得我想要的东西


基本上,如果可能的话,我希望根据运行时的数据类型对属性进行序列化。

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

您可以尝试以下操作:

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

在我看来,这是一个很好的json。

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

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

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

1.使用自定义转换器选择所有
int
属性 第一种方法是使用自定义的
JsonConverter
,它通过只包含类型为
int
的属性来序列化类或结构。代码可能如下所示:

{"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}
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();
    }
}
然后,您必须使用
jsonConverterateAttribute
来装饰您的类:

[JsonConverter(typeof(IntPropertyConverter))]
public class UrlStats
{
    // ...
}
免责声明:此代码只经过了非常粗略的测试


2.分别选择属性 第二种解决方案看起来更简单:可以使用
JsonIgnoreAttribute
来修饰要排除用于序列化的属性。或者,通过显式地包含要序列化的属性,可以从“黑名单”切换到“白名单”。下面是一些示例代码:

黑名单:(为了更好地了解情况,我对属性进行了重新排序)

[JsonObject(MemberSerialization.OptOut)]//这是默认值,可以省略
公共类UrlStats
{
[JsonIgnore]公共字符串URL{get;set;}
[JsonIgnore]公共列表总页面{get;set;}
[JsonIgnore]公共列表TotalTitles{get;set;}
[JsonIgnore]公共列表重复标题{get;set;}
[JsonIgnore]公共列表超长标题{get;set;}
公共int TotalPagesFound{get;set;}
公共整数TotalTitleTags{get;set;}
public int noduplicateTileTags{get;set;}
public int NoOverlengthTitleTags{get;set;}
}
白名单:(也重新排序)

[JsonObject(MemberSerialization.OptIn)]//这很重要!
公共类UrlStats
{
公共字符串URL{get;set;}
公共列表TotalPages{get;set;}
公共列表TotalTitles{get;set;}
公共列表标题{get;set;}
公共列表超长标题{get;set;}
[JsonProperty]公共int TotalPagesFound{get;set;}
[JsonProperty]public int TotalTitleTags{get;set;}
[JsonProperty]public int NoDuplicateTitleTags{get;set;}
[JsonProperty]public int NoOverlengthTitleTags{get;set;}
}

非常感谢,我实际上使用了corrego给出的简单解决方案,但我也会记住您的解决方案。@DineshAhuja在这种情况下,您应该接受corrego的答案。您好,我遇到了一个新的场景,其中我有EntityObject Racingreult,它在Model.Designer.cs中定义,它有15个以上的属性。我正在通过搜索数据库检索列表,但只想向客户端发送5个属性。正如您所知,我不能在Model.Designer.cs中放入类似于[JsonProperty]的内容,因此有什么方法可以发送一些属性。谢谢你advance@DineshAhuja我认为唯一的解决方案是使用自定义转换器类(就像我的第一种方法一样)。但您不必像这样使转换器通用。只能为模型类创建自定义转换器。但是,您必须在每次调用序列化或反序列化函数时指定转换器,因为您不能像我在解决方案的最后一段代码中所做的那样,在模型类中使用
JsonConverterAttribute
指定转换器。@Shawnery问题被标记为
json.net
,所以是的,我为Newtonsoft库编写了一个转换器类。返回
[JsonConverter(typeof(IntPropertyConverter))]
public class UrlStats
{
    // ...
}
[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; }
}