如何处理 JsonConvert.DeserializeObject 中的 null/empty 值

96

我有以下代码:

return (DataTable)JsonConvert.DeserializeObject(_data, (typeof(DataTable)));

然后,我尝试了:

var jsonSettings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore
};

return (DataTable)JsonConvert.DeserializeObject<DataTable>(_data, jsonSettings);

返回行抛出错误:

{"将值\"\"转换为类型 'System.Double' 时出错。"}

很多在线解决方案建议创建具有可空类型的自定义Class,但这对我不起作用。 我不能期望json以特定格式存在。 对于列计数、列类型或列名称,我没有任何控制权。


1
也许你应该使用 LINQ to JSON,获取一个 JObject 而不是创建一个 DataTable - Jon Skeet
如果您需要转换 DataTable,请使用专用转换器 DataTableConverter - Candide
2
你能分享一下导致问题的JSON示例吗? - dbc
@Candide 当使用 return JsonConvert.DeserializeObject<DataTable>(_data, new DataTableConverter()); 时出现相同的错误。 - Kyle
4个回答

257

你可以向 JsonConvert.DeserializeObject 提供设置,告诉它如何处理空值,在这种情况下,还有更多内容:

var settings = new JsonSerializerSettings
                    {
                        NullValueHandling = NullValueHandling.Ignore,
                        MissingMemberHandling = MissingMemberHandling.Ignore
                    };
var jsonModel = JsonConvert.DeserializeObject<Customer>(jsonString, settings);

1
这是完美的答案 - 我一直在搜寻解决方案,终于找到一个可行的。英雄般的地位。 - iTrout
7
MissingMemberHandling = MissingMemberHandling.Ignore 是默认设置,不需要添加。 - Uylenburgh
当我在类中反序列化基本类型(long,int)属性时,出现了错误。JSON来自不同的API,我无法控制。通用解决方案对我有用。谢谢Thomas。 - Satheesh K
3
我认为这些应该是反序列化器的默认设置。它不应该因为遇到空值而默认出错并破坏您的代码。 - SendETHToThisAddress

34

对于Thomas Hagström来说,有一种替代方案,也是我更喜欢的方案,就是在成员变量上使用property属性。

例如,当我们调用API时,它可能会返回错误消息,也可能不会返回,因此我们可以为ErrorMessage设置NullValueHandling属性:


    public class Response
    {
        public string Status;

        public string ErrorCode;

        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string ErrorMessage;
    }


    var response = JsonConvert.DeserializeObject<Response>(data);

这样做的好处在于隔离数据定义(what)和反序列化(use),反序列化不需要关心数据属性,因此两个人可以一起工作,而且反序列化语句会更加简洁清晰。


5
您可以订阅“Error”事件,并根据需要忽略序列化错误。
    static void Main(string[] args)
    {
        var a = JsonConvert.DeserializeObject<DataTable>("-- JSON STRING --", new JsonSerializerSettings
        {
            Error = HandleDeserializationError
        });
    }

    public static void HandleDeserializationError(object sender, ErrorEventArgs errorArgs)
    {
        var currentError = errorArgs.ErrorContext.Error.Message;
        errorArgs.ErrorContext.Handled = true;
    }

1
这样做虽然忽略了错误,但返回的 DataTable 对象为空。 - Kyle
你能发布那个JSON字符串,然后我会修改我的回答以更好地适应。 - DotNetHitMan

4
ASP.NET CORE: 接受的答案完美地解决了问题。但是为了使答案全局适用,在startup.cs文件中,在ConfigureServices方法中编写以下内容:
    services.AddControllers().AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
    });

答案已在 .Net Core 3.1 项目中进行了测试。

1
没有关于你正在访问哪些服务的上下文,答案将是不完整和错误的。 - vivek86
@vivek86 我已经更新了答案。你可以取消你的踩。 - M Fuat
这实际上是一个非常好的答案,适用于当代代码,因为设置全局JSON反序列化选项的问题经常浮出水面。 - ZXX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接