【问题标题】:unable to deserialize null value in c#无法在c#中反序列化空值
【发布时间】:2019-08-21 10:00:47
【问题描述】:

我正在使用下面的代码返回任务,但我不知道如何反序列化空值。

finalResult 值为 Null 时如何处理代码。

public async Task<T> PostAsync<T>(JObject parameters)
{
    string sasURL = await GenerateLogicAppSASUrl();
    var param = new StringContent(parameters.ToString(), Encoding.UTF8, "application/json");
    var httpCall = await client.PostAsync(sasURL, param);
    var result = await httpCall.Content.ReadAsStringAsync();
    var finalResult = JObject.Parse(result)["Column1"]?.ToString();  
    return  JsonConvert.DeserializeObject<T>(finalResult); // what to return if finalResult value here is null
}

【问题讨论】:

  • 我认为这里已经回答了类似的问题:stackoverflow.com/questions/31813055/…
  • data确切值是多少?
  • finalResult 值将是 null 或一些通用类型数据
  • return null,不要尝试反序列化,反正Newtonsoft Json可以处理null值,可以按设置反序列化
  • @MrinalKamboj 该行只是尝试反序列化 finalResult 如果它为空,否则就按原样返回它......

标签: c# .net asp.net-core


【解决方案1】:

JsonConvert.DeserializeObject&lt;T&gt;() 在参数为空时抛出 ArgumentNullException

如果您的 finalResult 变量为空,您可以抛出异常,或者从您的方法返回 null 而不是反序列化它:

return finalResult == null ? default(T): JsonConvert.DeserializeObject<T>(finalResult);

【讨论】:

  • @chrisb-de OP 提到它有空值
  • 当然。 await httpCall.Content.ReadAsStringAsync() 可以检索空值。但我看不到对 T 本身的任何限制。当你调用像PostAsync&lt;decimal&gt;(parameters) 这样的方法时,预期的结果可能根本不为空。
【解决方案2】:

解决方案 1:

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

var result = JsonConvert.DeserializeObject<T>(data, jsonSettings); // jsonSettings are explicitly supplied

Json.Net例子理解上面的设置

void Main()
{
    Test t = new Test 
    {
     Str = null,
     Val=1
    };

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

    var json = JsonConvert.SerializeObject(t,jsonSettings);

    json.Dump();    

    var result = JsonConvert.DeserializeObject<Test>(json, jsonSettings);

    result.Dump();
}

public class Test
{
    public string Str {get;set;}

    public int Val {get; set;}
}

结果:

解释:

  1. 空值处理 Json 设置在序列化过程中忽略空值
  2. 在反序列化过程中,引入了相同的值并带有空值
  3. 空值必须是字段而不是整个对象,如果整个对象为空,则不需要序列化,反序列化,可以通过逻辑抢占

解决方案 2:

return (finalResult != null) ? JsonConvert.DeserializeObject<T>(finalResult) : default(T)

我的首选是Solution1,因为它将在序列化程序库级别内部处理空值

【讨论】:

  • Solution1 抛出错误为“System.ArgumentNullException: 'Value cannot be null. Parameter name: value'”
  • 您从 Json.Net DeserializeObject 调用中得到异常,然后我会感到惊讶,这是记录的默认方式
  • @Mrinal Kaboj:您的第一个解决方案需要对 JsonConvert.DeserializeObject 进行额外设置。我想在整个代码中都有这些设置。在我看来是一场噩梦。当数据为空时只返回默认值似乎是最干净的方法。
  • @chrisb-de 没那么糟糕,我们使用像工厂这样的模式来避免重复创建对象,并使代码干净。事实上,这些设置也可以在项目级别
  • 当一个简单的if (data == null) return default; 就足够了,为什么还要在项目级别或其他任何地方配置它呢?我没有看到引入更多复杂性来解决这样一个微不足道和可预测的问题的好处。所以我宁愿选择第二种解决方案。 :-)
【解决方案3】:

你可以像这样创建一个扩展字符串方法:

public static dynamic Deserialize(this string stg, Type typeWanted)
    {
         var model = Activator.CreateInstance(typeWanted);

        if (string.IsNullOrEmpty(stg))
            return model;

        model = JsonConvert.DeserializeObject(stg, typeWanted);

        return model;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-18
    • 1970-01-01
    • 2019-07-07
    相关资源
    最近更新 更多