代码之家  ›  专栏  ›  技术社区  ›  SHEKHAR SHETE

读取特定JSON字符串时出现对象引用错误?

  •  0
  • SHEKHAR SHETE  · 技术社区  · 10 年前

    我用过 JSON to C# Class Converter 并生成以下类:

    JSON文件

    {"ios_info":{"serialNumber":"F2LLMBNJFFF","imeiNumber":"01388400413235","meid":"","iccID":"8901410427640096045","firstUnbrickDate":"11\/27\/13","lastUnbrickDate":"11\/27\/13","unbricked":"true","unlocked":"false","productVersion":"7.1.2","initialActivationPolicyID":"23","initialActivationPolicyDetails":"US AT&T Puerto Rico and US Virgin Islands Activation Policy","appliedActivationPolicyID":"23","appliedActivationDetails":"US AT&T Puerto Rico and US Virgin Islands Activation Policy","nextTetherPolicyID":"23","nextTetherPolicyDetails":"US AT&T Puerto Rico and US Virgin Islands Activation Policy","macAddress":"ACFDEC6C988A","bluetoothMacAddress":"AC:FD:EC:6C:98:8B","partDescription":"IPHONE 5S SPACE GRAY 64GB-USA"},"fmi":{"@attributes":{"version":"1","deviceCount":"1"},"fmipLockStatusDevice":{"@attributes":{"serial":"F2LLMBNJFFFQ","imei":"013884004132355","isLocked":"true","isLost":"false"}}},"product_info":{"serialNumber":"F2LLMBNJFFF","warrantyStatus":"Apple Limited Warranty","coverageEndDate":"11\/25\/14","coverageStartDate":"11\/26\/13","daysRemaining":"497","estimatedPurchaseDate":"11\/26\/13","purchaseCountry":"United States","registrationDate":"11\/26\/13","imageURL":"http:\/\/service.info.apple.com\/parts\/service_parts\/na.gif","explodedViewURL":"http:\/\/service.info.apple.com\/manuals-ssol.html","manualURL":"http:\/\/service.info.apple.com\/manuals-ssol.html","productDescription":"iPhone 5S","configDescription":"IPHONE 5S GRAY 64GB GSM","slaGroupDescription":"","contractCoverageEndDate":"11\/25\/15","contractCoverageStartDate":"11\/26\/13","contractType":"C1","laborCovered":"Y","limitedWarranty":"Y","partCovered":"Y","notes":"Covered by AppleCare+ - Incidents Available","acPlusFlag":"Y","consumerLawInfo":{"serviceType":"","popMandatory":"","allowedPartType":""}}}
    

    从上面的JSON读取所有数据,但 only the line at which i get error is in reading the JSON is:

    fmi":{"@attributes":{"version":"1","deviceCount":"1"},"fmipLockStatusDevice":{"@attributes":{"serial":"F2LLMBNJFFFQ","imei":"013884004132355","isLocked":"true","isLost":"false"}}},
    

    错误:

    对象引用未设置为对象的实例。

    public class AppleAPI
    {
        public IosInfo ios_info { get; set; }
        public ProductInfo product_info { get; set; }
        public Fmi fmi { get; set; }
        public class IosInfo
        {
            public string serialNumber { get; set; }
            public string imeiNumber { get; set; }
            public string meid { get; set; }
            public string iccID { get; set; }
            public string firstUnbrickDate { get; set; }
            public string lastUnbrickDate { get; set; }
            public string unbricked { get; set; }
            public string unlocked { get; set; }
            public string productVersion { get; set; }
            public string initialActivationPolicyID { get; set; }
            public string initialActivationPolicyDetails { get; set; }
            public string appliedActivationPolicyID { get; set; }
            public string appliedActivationDetails { get; set; }
            public string nextTetherPolicyID { get; set; }
            public string nextTetherPolicyDetails { get; set; }
            public string macAddress { get; set; }
            public string bluetoothMacAddress { get; set; }
            public string partDescription { get; set; }
        }
    
        public class ConsumerLawInfo
        {
            public string serviceType { get; set; }
            public string popMandatory { get; set; }
            public string allowedPartType { get; set; }
        }
    
    
        public class ProductInfo
        {
            public string serialNumber { get; set; }
            public string warrantyStatus { get; set; }
            public string coverageEndDate { get; set; }
            public string coverageStartDate { get; set; }
            public string daysRemaining { get; set; }
            public string estimatedPurchaseDate { get; set; }
            public string purchaseCountry { get; set; }
            public string registrationDate { get; set; }
            public string imageURL { get; set; }
            public string explodedViewURL { get; set; }
            public string manualURL { get; set; }
            public string productDescription { get; set; }
            public string configDescription { get; set; }
            public string slaGroupDescription { get; set; }
            public string contractCoverageEndDate { get; set; }
            public string contractCoverageStartDate { get; set; }
            public string contractType { get; set; }
            public string laborCovered { get; set; }
            public string limitedWarranty { get; set; }
            public string partCovered { get; set; }
            public string notes { get; set; }
            public string acPlusFlag { get; set; }
            public ConsumerLawInfo consumerLawInfo { get; set; }
        }
    
        public class Fmi
        {
            public Attributes invalid_nameattribute { get; set; }
            public FmipLockStatusDevice fmipLockStatusDevice { get; set; }
        }
        public class FmipLockStatusDevice
        {
            public Attributes2 invalid_nameattribute2 { get; set; }
        }
        public class Attributes
        {
            public string version { get; set; }
            public string deviceCount { get; set; }
        }
    
        public class Attributes2
        {
            public string serial { get; set; }
            public string imei { get; set; }
            public string isLocked { get; set; }
            public string isLost { get; set; }
        }
    }
    

    读取JSON:

    string responseText = string.Empty;
    AppleAPI appobj = new AppleAPI();
    responseText = appobj.VerifyAppleESN(newEsn);
    var resobj = JsonConvert.DeserializeObject<AppleAPI>(responseText.Replace("@",string.Empty));
    lblSerialNumber.Text = resobj.product_info.serialNumber;
    .
    .
    lblappliedActivationDetails.Text = resobj.ios_info.appliedActivationDetails;
    .
    .
    //getting here error below line: Object ref notset to instance of object
    lblfmiVersion.Text = resobj.fmi.invalid_nameattribute.version;
    

    有什么想法吗?

    1 回复  |  直到 10 年前
        1
  •  1
  •   Brian Rogers    10 年前

    如果你得到 Object Reference not set to an instance of object. 这意味着您正在尝试访问空对象的财产。既然你说发生在这条线上:

    lblfmiVersion.Text = resobj.fmi.invalid_nameattribute.version;
    

    这可能意味着 resobj , resobj.fmi resobj.fmi.invalid_nameattribute 为空。忽略了在代码中应该有适当的空检查以帮助避免这种情况的事实,让我们问一个问题,如果反序列化成功,为什么这些对象中的任何一个都是空的?也许有些数据最终没有正确反序列化。

    使用Json.Net进行反序列化时,重要的是要知道,如果类的任何成员在Json中没有匹配的财产,那么Json.Net将跳过这些成员,从而保留其默认值,例如。 null 。因此,使用null的一个可能原因是类中属性的名称与JSON中的名称不匹配。

    如果我们看看你的 Fmi 类中,一个立即跳出的问题是它有一个名为 invalid_nameattribute 。在JSON中,没有这样的属性。相反,有一个名为 @attributes 你的 FmipLockStatusDevice 类也有同样的问题。因为它们不匹配,所以在反序列化期间没有填充这些财产,所以它们为空。

    那么我们如何解决这个问题?

    这很简单:添加 [JsonProperty] 属性将它们映射到正确的JSON财产。(当你在做的时候,你也可以考虑将C#类中那些财产的名称更改为一些实际有意义的名称,比如“Attributes”。)

    public class Fmi
    {
        [JsonProperty("@attributes")]
        public Attributes invalid_nameattribute { get; set; }
        public FmipLockStatusDevice fmipLockStatusDevice { get; set; }
    }
    
    public class FmipLockStatusDevice
    {
        [JsonProperty("@attributes")]
        public Attributes2 invalid_nameattribute2 { get; set; }
    }
    

    好的,既然你有了解决方案,你应该问问自己,你是怎么一开始就陷入这种情况的,以及你将来如何避免这种情况?

    你说过你用过 json2csharp.com 生成类。您需要意识到,该工具不是万无一失的,并且不会总是能够生成正确的类来处理JSON。当JSON属性名称包含标点符号或空格或以数字开头时,这是正确的,因为这些不能转换为有效的C#属性名称。在这些情况下,json2csharp.com将生成一个以“invalid”开头的属性名。您需要查找这些,并对类进行手动调整以解决问题。不要盲目地使用生成的类并假设它们是正确的。

    希望这有帮助。