Json.NET JsonConvert.DeserializeObject()返回空值

本文关键字:返回 空值 DeserializeObject NET JsonConvert Json | 更新日期: 2023-09-27 18:08:54

我试图反序列化这个字符串:

string _jsonObject = {'"Ad'":{'"Type'":'"Request"',
         '"IdAd'":'"xxx@xxx.com'",
         '"Category'":'"cat'",
         '"SubCategory'":'"subcat'"},
'"Position'":{'"Latitude'":'"38.255'",
              '"Longitude'":'"1.2'",
              '"Imei'":'"0123456789'"};
}";
Message _message = JsonConvert.DeserializeObject<Message>(_jsonObject);

适用于"Ad",但不能实例化"Position"。知道吗?

Json.NET JsonConvert.DeserializeObject()返回空值

我忘记把属性设为公共了。别忘了……

为了帮助那些可能遇到这个问题的人,或者与之相关的人……

在我的例子中,我有一个对象和其他对象的数组,这些子对象上的一个引用类型属性在反序列化后总是为空。我尝试了各种方法,包括下载JSON。Net源代码并逐步通过它来找到故障点。

长话短说,这个问题当然是我自己的。以下是我的JSON和类的高度简化版本。 JSON
{
    "$id": "1",
    "RowCount": 10,
    "Rows": [{
        "$id": 2",
        "ItemId": "1",
        "ItemName": "Some Item",
        "Owner": {
            "Name": "John Doe",
            "Id": "711D04F5-586F-4FD4-8369-4C00B51DD86F",
            // other properties...
        },
        "OwnerId": "711D04F5-586F-4FD4-8369-4C00B51DD86F"
    },
    // more rows
    ]
}

public class Items
{
    public int RowCount { get; set; }
    public IEnumerable<Item> Rows { get; set; }
}
public class Item
{
    private string ownerId;
    public string ItemId { get; set; }
    public string ItemName { get; set; }
    public Person Owner { get; set; }
    public string OwnerId
    {
        get { return this.ownerId; }
        set {
            if (value != this.ownerId)
            {
                this.Owner = null;
            }
            this.ownerId = value;
        }
    }
}
public class Person
{
    public string Name { get; set; }
    public string Id { get; set; }
    // other properties
}

实际情况是,由于Owner属性在JSON中出现在OwnerId属性之前,当设置OwnerId属性时,setter代码确定当前值与要设置的值不相同(因为当前值为空),因此将Owner属性设置为空。

为了修复它,我还检查了针对Owner对象的id设置的值,如果它们相同,则跳过将Owner设置为null。

无可否认,我的问题的原因可能对每个人都不一样,但这至少是一个警告,提醒你在反序列化期间初始化对象时仔细检查发生了什么。

我不知道你是如何试图反序列化的,但这应该工作....

string json = "{'"Ad'":{'"Type'":'"Request'",         '"IdAd'":'"xxx@xxx.com'",         '"Category'":'"cat'",         '"SubCategory'":'"subcat'"},'"Position'":{'"Latitude'":'"38.255'",              '"Longitude'":'"1.2'",              '"Imei'":'"0123456789'"}}";
var obj = JsonConvert.DeserializeObject<RootObject>(json);

public class Ad
{
    public string Type { get; set; }
    public string IdAd { get; set; }
    public string Category { get; set; }
    public string SubCategory { get; set; }
}
public class Position
{
    public string Latitude { get; set; }
    public string Longitude { get; set; }
    public string Imei { get; set; }
}
public class RootObject
{
    public Ad Ad { get; set; }
    public Position Position { get; set; }
}

在我的例子中,我的类属性有内部setter ,在将它们设置为public之后,问题就解决了。

在我的例子中有一个更微妙的错误。很容易在json键中错误地添加前导或尾随空格。当发生这种情况时,键无法识别,并且试图反序列化它时将值设置为null。

示例:{" id": 123}
由于前导空格 " id", id字段无法被识别。要修复它,请将json改为"id"

确保JSON中的数组名称与类中的属性名称匹配

说明(寻找"组件"):

JSON:

{  
  "Components": [
    {
      "Attribute1": "ABC",
      "Attribute2": "XYZ"      
    }
  ]
}
类:

public class MyClass
{
    public IList<Component> Components { get; set; }
}

反序列化:

JsonConvert.DeserializeObject<MyClass>(File.ReadAllText(@"ComponentSet.json"))

我的问题是我在JSON字符串的开头包含了类名。我复制粘贴了另一个类的序列化输出,其中包含我想要反序列化的类,并且我有目的地包含了类名,认为这是正确的JSON字符串。一旦我从JSON字符串中删除了类名,它就可以很好地反序列化了。

本文有助于实现这一点:https://social.msdn.microsoft.com/Forums/windowsapps/en-US/4d766a28-ff38-477f-8abf-48ed01f74cd2/jsonconvertdeserializeobjectlttgtjsonstring-returning-all-propertieslttgt-as-null?forum=wpdevelop

我在这里没有看到这个答案,所以我把它包括进来,希望它能帮助那些犯了和我一样愚蠢错误的人。

我使用Newtonsoft从未遇到过任何问题。Json,但决定在最新的项目中使用内置的Json库。以null结果结束。结果显示以下操作将失败:

JSON:

{
   "myProperty": "abc"
}
类:

public void MyClass
{
   public string MyProperty { get; set; }
}

为什么会失败?"myProperty"in json是驼色大小写(以小写字母开头),而MyClass中的MyProperty以大写字母开头。如果你让这两种情况相同,它是有效的。我试着弄清楚如何为整个应用程序配置大小写不敏感,但显然这是不可能做到的,所以我回到了Newtonsoft。JSON,问题就解决了。

在我的例子中,这是因为我的类没有公共构造函数。

这是我的类最初的样子:

public class TreeGroup
{
    public string Name { get; set; }
    public SiteGroup Group { get; set; }
    public List<TreeMimicObject> Children { get; set; }
   
    public TreeGroup(SiteGroup item)
    {
        // Notice this constructor takes a SiteGroup object and there 
        // is no default constructor
    }
}

所以我把上面的类改成了:

public class TreeGroup
{
    public string Name { get; set; }
    public SiteGroup Group { get; set; }
    public List<TreeMimicObject> Children { get; set; }
    public TreeGroup()
    {
        // Added this default constructor here!!
    }
    public TreeGroup(SiteGroup item)
    {
        // ...
    }
}

成功了!

在我的情况下,问题是deserializeobject返回null时,试图将null值从json转换为int

    public class ItemCalcResModel
    {
        public int cartId;
    }

我通过在项目中启用nullable解决了这个问题:

    #nullable enable
    public class ItemCalcResModel
    {
        public int? cartId;
    }

在我的情况下,这是因为我忘记了用JsonPropertyName属性装饰Location属性。修改:

public LatLongLocation Location {get; set; }

:

[JsonPropertyName("location")]
public LatLongLocation Location {get; set; }

在我的例子中,我天真地试图在构造函数中执行反序列化的额外逻辑。

当试图通过var deserializedItem = JsonConvert.DeserializeObject<MyClass>(item);进行反序列化时,MyClass的构造函数将显示所有值为空,即使反序列化之前的日志语句显示了一个有效的JSON字符串。

所以如果它对你或其他人有帮助,那可能是另一个需要检查的领域。在您的例子中,Message类函数可能包含额外的逻辑。

public Message(string _thing1, string _thing2)
{
   // setting values here
   thing1 = _thing1;
   byte[] data = Convert.FromBase64String(thing1);
   // doing more stuff with data
   thing2 = _thing2;
}