在datamember“__type”上反序列化JSON的问题

简而言之,我正在尝试从Bing Maps Geocoding REST API反序列化JSON响应,

我创建了我的响应类,现在当我试图实际反序列化响应时,我收到以下错误:

不期望输入数据合同名称为“{1}:{2}”的“{0}”。 考虑使用DataContractResolver或将任何静态未知的类型添加到已知类型列表中 – 例如,通过使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型列表中。

它试图反序列化这一行JSON,并失败:

"__type": "Location:http:\/\/schemas.microsoft.com\/search\/local\/ws\/rest\/v1", 

我的响应类看起来像这样

  [DataContract] public class GeoResponse { [DataMember(Name = "statusDescription")] public string StatusDescription { get; set; } [DataMember(Name = "statusCode")] public string StatusCode { get; set; } [DataMember(Name = "resourceSets")] public ResourceSet[] resourceSets { get; set; } [DataContract] public class ResourceSet { [DataMember(Name = "__type", IsRequired=false)] public string type { get; set; } [DataMember(Name = "estimatedTotal")] public string EstimatedTotal { get; set; } [DataMember(Name = "resources")] public List resources { get; set; } [DataContract] public class Resources { [DataMember(Name = "name")] public string Name { get; set; } [DataMember(Name = "point")] public Point point { get; set; } [DataContract] public class Point { [DataMember(Name = "type")] public string Type { get; set; } [DataMember(Name = "coordinates")] public string[] Coordinates { get; set; } } [DataMember(Name = "address")] public Address address { get; set; } [DataContract] public class Address { [DataMember(Name = "addressLine")] public string AddressLine { get; set; } [DataMember(Name = "countryRegion")] public string CountryRegion { get; set; } [DataMember(Name = "formattedAddress")] public string FormattedAddress { get; set; } [DataMember(Name = "locality")] public string Locality { get; set; } [DataMember(Name = "postalCode")] public string PostalCode { get; set; } } [DataMember(Name = "confidence")] public string Confidence { get; set; } [DataMember(Name = "entityType")] public string EntityType { get; set; } } } } } 

我的方法我用来反序列化我的JSON响应:

 private static GeoResponse CallGeoWS(string address) { string url = string.Format( "http://dev.virtualearth.net/REST/v1/Locations?q={0}&key={1}", HttpUtility.UrlEncode(address), bingkey ); var request = (HttpWebRequest)HttpWebRequest.Create(url); request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate"); request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(GeoResponse)); var res = (GeoResponse)serializer.ReadObject(request.GetResponse().GetResponseStream()); return res; } 

首先,请注意您引用的方法( http://dev.virtualearth.net/REST/v1/Locations?q=Wiertzstraat+43+1047+Brussel&key=BingMapsKey )与一个方法相比产生不同的响应您正在尝试使用DataContract类进行映射。 响应在此处描述: http : //msdn.microsoft.com/en-us/library/ff701711.aspx

我为该响应创建了一个DataContract:

  [DataContract]
公共类LocationQueryResponse
 {
     [数据成员]
     public string authenticationResultCode {get; 组;  }
     [数据成员]
     public string brandLogoUri {get; 组;  }
     [数据成员]
    公共字符串版权{get; 组;  }
     [数据成员]
     public string statusCode {get; 组;  }
     [数据成员]
     public string statusDescription {get; 组;  }
     [数据成员]
     public string traceId {get; 组;  }

     [数据成员]
     public ResourceSet [] resourceSets {get; 组;  }

     [DataContract]
    公共类ResourceSet
     {
         [数据成员]
         public int estimatedTotal {get; 组;  }

         [数据成员]
         public Resource [] resources {get; 组;  }

         [DataContract(Namespace =“http://schemas.microsoft.com/search/local/ws/rest/v1”,Name =“Location”)]
        公共课资源
         {
             [数据成员]
             public string __type {get; 组;  }

             [数据成员]
             public double [] bbox {get; 组;  }

             [数据成员]
            公共字符串名称{get; 组;  }

             [数据成员]
            公共点{get; 组;  }

             [DataContract]
            公共课点
             {
                 [数据成员]
                公共字符串类型{get; 组;  }

                 [数据成员]
                 public string [] coordinates {get; 组;  }
             }

             [数据成员]
            公共地址{get; 组;  }

             [DataContract]
            公共类地址
             {
                 [数据成员]
                 public string addressLine {get; 组;  }
                 [数据成员]
                 public string adminDistrict {get; 组;  }
                 [数据成员]
                 public string adminDistrict2 {get; 组;  }
                 [数据成员]
                 public string countryRegion {get; 组;  }
                 [数据成员]
                 public string formattedAddress {get; 组;  }
                 [数据成员]
                 public string locality {get; 组;  }
                 [数据成员]
                 public string postalCode {get; 组;  }
             }

             [数据成员]
            公共字符串信心{get; 组;  }

             [数据成员]
             public string entityType {get; 组;  }
         }

     }
 }

首先,即使我创建了一个正确的DataContract,它也不起作用,并且它生成了与您呈现的相同的exception。 经过一些研究后,我发现“__type”字段对DataContractJsonSerializer具有特殊含义,表示对象应反序列化的类型。 为了完成这项工作,我将Name和Namespace属性添加到R​​esource类的DataContract属性中(请检查上面的代码)。

我对WCF和JSON有很多经验,之前从未遇到过这个问题。 它似乎是一个相当模糊的,__ type字段似乎不符合标准,而是Microsoft特定的function。 相当恼人的是__type字段似乎只在某些特定情况下。 例如,如果在JSON文档中有前面有空格,则反序列化器会忽略它并且不会抛出任何exception。 我在最初用于测试的文档中有这样一个空白区域,这就是为什么我在那时没有得到错误。

希望这个终于有所帮助。 🙂