【问题标题】:Json.NET: How to perform implicit conversion of an object before serializing?Json.NET:如何在序列化之前执行对象的隐式转换?
【发布时间】:2016-06-23 04:50:55
【问题描述】:

我有一个有很多“可选布尔值”的类——布尔值可能是真、假或空。在 .NET 中表示这一点的最常见方法是使用 bool?,但它至少占用内存中的 2 个字节(参见 this question),所以我编写了自己的 OptionalBool 结构,它只占用 1 个字节和可以隐式转换为bool?

我的问题是,我有这样的课程:

public class PartnerLoginOptions
{
    public string Username { get; set; }
    public string Password { get; set; }
    public string DeviceModel { get; set; }
    public string Version { get; set; }

    public OptionalBool IncludeUrls { get; set; }
    public OptionalBool ReturnDeviceType { get; set; }
    public OptionalBool ReturnUpdatePromptVersions { get; set; }
}

如何让 Json.NET 在序列化时执行从 OptionalBoolbool? 的隐式转换?例如,如果 IncludeUrlsdefault(OptionalBool)(即“null”),ReturnDeviceType 为真,ReturnUpdatePromptVersions 为假,那么输出的 JSON 将类似于

{
    "includeUrls": null,
    "returnDeviceType": true,
    "returnUpdatePromptVersions": false
}

在给定PartnerLoginOptions 对象的情况下,我该怎么做?我到目前为止的代码是

var body = JsonConvert.SerializeObject(options, new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};

编辑:如果有用,hereOptionalBool 的源代码。

【问题讨论】:

  • 您是否看过创建自定义 json 转换器?

标签: c# .net json serialization json.net


【解决方案1】:

回答您的问题,您可以执行以下操作:

public class PartnerLoginOptions
{
    public string Username { get; set; }
    public string Password { get; set; }
    public string DeviceModel { get; set; }
    public string Version { get; set; }

    [JsonIgnore]
    public OptionalBool IncludeUrls { get; set; }

    [JsonProperty("IncludeUrls")]
    public bool? IncludeUrlsConverted 
    { 
        get { return (bool?)IncludeUrls; } // your conversion here
        set { IncludeUrls = (OptionalBool)value; } // your backwards conversion here
    }
}

或者你可以自己写JsonConverter

但是,对我来说,您的 OptionalBool 似乎是过度工程。 2 个字节绝对不算多,我无法想象真正需要它的情况,同时它会产生如此多的不兼容问题,产生转换器和不同的 hack,并降低可读性。
考虑改成bool?

【讨论】:

    【解决方案2】:

    如果您真的想这样做,您可以为OptionalBool 定义自定义转换器:

    public class OptionalBoolConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(OptionalBool) == objectType;
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var converted = (bool?) (OptionalBool) value;
    
            writer.WriteValue(converted);
        }
    }
    

    然后这样使用:

    var test = new PartnerLoginOptions
            {
                ReturnDeviceType = true,
                ReturnUpdatePromptVersions = false
            };
            var json = JsonConvert.SerializeObject(test, new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver(),
                Converters = new JsonConverter[] {new OptionalBoolConverter()}
            });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多