JSON.. NET JsonConvert.SerializeObject()的特殊行为

本文关键字:NET JsonConvert SerializeObject JSON | 更新日期: 2023-09-27 18:05:19

我的情况是这样的。我们正处在决定使用哪种Json序列化工具的关键时刻。我们正在考虑Newtonsoft。JSON和Microsoft JavaScriptSerializer。Newtonsoft。JSON是我们的第一次尝试,但是我们发现了一些奇怪的行为。下面是示意图代码来说明这个问题。假设我们有如下的类配置:

interface IA<T>
{
    T Id { get; set; }
}
[DataContractAttribute]
abstract class A : IA<string>
{
    protected A() { }
    [DataMemberAttribute]
    public virtual  string Id
    {
        get;
        set;
    }
}
class B : A
{
    public string P1 { get; set; }
    public string P2 { get; set; }
}

如果我们将使用Newtonsoft。Json的JsonConvert类从B类中获取Json字符串,我们可以使用以下代码:

        B b = new B();
        string jsonOutput = Newtonsoft.Json.JsonConvert.SerializeObject(b, 
            new Newtonsoft.Json.JsonSerializerSettings() { 
                NullValueHandling = Newtonsoft.Json.NullValueHandling.Include 
            });

但不幸的是,只有Id属性会反映在结果JSON字符串中。B类的所有其他属性都不会显示出来。相反,JavaScriptSerializer会像预期的那样生成JSON字符串。类B是我们的类,类A和接口IA来自第三方库,所以我们不能修改。此外,我们也不想在我们的类上使用数据契约序列化注释,只是为了安抚挑剔的json序列化器。

是否有办法指示Newtonsoft.Json.JsonConvert序列化所有属性,无论是否有注释?

编辑:虽然@LB提供了可接受的答案,@dbc提出了更全面的解决方案,所以如果你想看到它,只需跟随他提供的链接作为这个问题的副本。

JSON.. NET JsonConvert.SerializeObject()的特殊行为

Json不需要DataContractAttributeDataMemberAttribute。网删除它们,你的代码就可以工作了....

要么在所有属性中使用它们,要么不使用它们

见http://www.newtonsoft.com/json/help/html/DataContractAndDataMember.htm

——编辑——

如果你不想使用任何Attributes,那么你可以创建一个自定义的ContractResolver

public class MyDefaultContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var result = base.CreateProperties(type, memberSerialization).ToList();
        result.ForEach(x => { x.Ignored = false; }); // <-- Include or not? 
        return result;
    }
}

并将代码序列化为:

string jsonOutput = Newtonsoft.Json.JsonConvert.SerializeObject(b,
new Newtonsoft.Json.JsonSerializerSettings()
{
    NullValueHandling = Newtonsoft.Json.NullValueHandling.Include,
    ContractResolver = new MyDefaultContractResolver()
});