NewtonSoft Json DeserializeObject 空 Guid 字段

Posted

技术标签:

【中文标题】NewtonSoft Json DeserializeObject 空 Guid 字段【英文标题】:NewtonSoft Json DeserializeObject empty Guid field 【发布时间】:2014-03-21 10:09:04 【问题描述】:

我正在使用带有 html CSS jQuery KnockoutJs 前端的 ASP.NET MVC C#。

我的 HTML 页面上有一个模式联系表。这个想法是,如果我创建一个新联系人,模态表单会弹出一个空白值,包括一个空白的隐藏 id 字段。

如果我编辑联系人,则会弹出模式表单,其中包含已填写的字段,包括隐藏的 id 字段。

在我的控制器中,我打算这样做:

public JsonResult Contact(string values)

    var contact = JsonConvert.DeserializeObject<contact>(values);

    if (contact.Id.Equals(Guid.Empty))
    
         // create a new contact in the database
     else
    
        // update an existing one
    

但是,我收到一条错误消息,提示 can't convert "" to type Guid

你如何使用 NewtonSoft Json 解决这个问题,我在 Custom JsonConverter 上查看了here,它似乎是正确的,但我不知道该去哪里有了这个。

【问题讨论】:

您是否尝试过将contact.Id 属性设为可空?这可能会解决它。 我使用数据库中使用的Contact 模型,因此将其设为可空会很糟糕。 【参考方案1】:

自定义转换器看起来像这样,但我觉得对于如此微不足道的事情来说它有点矫枉过正。

/// <summary>
/// Converts a <see cref="Guid"/> to and from its <see cref="System.String"/> representation.
/// </summary>
public class GuidConverter : JsonConverter

    /// <summary>
    /// Determines whether this instance can convert the specified object type.
    /// </summary>
    /// <param name="objectType">Type of the object.</param>
    /// <returns>Returns <c>true</c> if this instance can convert the specified object type; otherwise <c>false</c>.</returns>
    public override bool CanConvert(Type objectType)
    
        return objectType.IsAssignableFrom(typeof(Guid));
    

    /// <summary>
    /// Reads the JSON representation of the object.
    /// </summary>
    /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
    /// <param name="objectType">Type of the object.</param>
    /// <param name="existingValue">The existing value of object being read.</param>
    /// <param name="serializer">The calling serializer.</param>
    /// <returns>The object value.</returns>
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        try
        
            return serializer.Deserialize<Guid>(reader);
        
        catch
        
            return Guid.Empty;
        
    

    /// <summary>
    /// Writes the JSON representation of the object.
    /// </summary>
    /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
    /// <param name="value">The value.</param>
    /// <param name="serializer">The calling serializer.</param>
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    
        serializer.Serialize(writer, value);
    

用法:

class Contact

    [JsonConverter(typeof(GuidConverter))]
    public Guid Id  get; set; 

或者:

var contact = JsonConvert.DeserializeObject<contact>(values, new GuidConverter());

编辑

我认为你的 JSON 看起来很像这样:


    "id": "",
    "etc": "..."

如果您可以这样做,问题可能会得到解决:


    "id": null,
    "etc": "..."

【讨论】:

现在测试一下 基本上,它所做的只是将默认转换器包装在 try-catch 块中。如果转换失败,则默认为Guid.Empty。不是最有效的解决方案。例如,您可以首先使用String.IsNullOrEmpty() 来避免异常。 最好的解决方案是在 JSON 数据中完全不包含 Id 属性。你能做到吗? 你会把它放在哪里,你是说遍历传递回操作的字符串并找到 id 并将 guid.empty 放入其中吗? 我不能,因为我试图在整个应用程序中实现单一的模态标准,所以前端只需要更新一个地方,后端也一样【参考方案2】:

我遇到了 Guid.Empty (00000000-0000-0000-0000-000000000000) 值被反序列化为 Null 指南导致错误的问题。当我将 JsonSerializerSettings.DefaultValueHandling 值设置为 DefaultValueHandling.IgnoreAndPopulate 时,反序列化 Guid 属性被设置为默认值

var serializedObject = JsonConvert.DeserializeObject<T>(serializedString, new JsonSerializerSettings  DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate );

【讨论】:

这个答案只是帮助我完成了 2 小时的调试会话。谢谢!【参考方案3】:

GUID 和 JSON 字符串的完整示例

string content = "\"data\":\"Type\":\"Foo\",\"Description\":\"bar \",\"Software\":\"baz\",\"Version\":\"qux\",\"Url\":\"http://example.com\",\"DatabasePortNumber\":1,\"Id\":\"2cdc66f1-0000-0000-39ac-233c00000000\"";

var result_SystemText = System.Text.Json.JsonSerializer.Deserialize<SystemApplicationResponse>(content);  //Will result in null-object
var result_Newtonsoft = Newtonsoft.Json.JsonConvert.DeserializeObject<SystemApplicationResponse>(content); //Will result in correctly serialized object

    public class SystemApplicationResponse
    
        public SystemApplicationDto Data  get; set; 
    


    public class SystemApplicationDto
    
        public SystemApplicationDtoType Type  get; set; 

        public string Description  get; set; 

        public string Software  get; set; 

        public string Version  get; set; 
        public string Url  get; set; 

        public int DatabasePortNumber  get; set; 
        public System.Guid Id  get; set; 
    

    public enum SystemApplicationDtoType
    
        Foo = 0
    

参考:https://github.com/dotnet/runtime/issues/31465#

【讨论】:

以上是关于NewtonSoft Json DeserializeObject 空 Guid 字段的主要内容,如果未能解决你的问题,请参考以下文章

无法将类型“newtonsoft.json.linq.jtoken”隐式转换为 newt“newtonsoft.json.linq.jvalue”

从 JSON 检索项目时获取“无法将 Newtonsoft.Json.Linq.JObject 转换为 Newtonsoft.Json.Linq.JToken”

使用 Newtonsoft.Json 解析 JSON 时出错

Newtonsoft.Json,填充字典失败

Newtonsoft.Json(Json.net) 的使用

Newtonsoft.Json(Json.Net)学习笔记