Десериализовать XML геокодирования Google с помощью Datacontract в C # - PullRequest
3 голосов
/ 23 сентября 2011

У меня есть следующий Google геокодирование XML

<GeocodeResponse> 
 <status>OK</status> 
 <result> 
  <type>street_address</type> 
  <formatted_address>1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA</formatted_address> 
  <address_component> 
   <long_name>1600</long_name> 
   <short_name>1600</short_name> 
   <type>street_number</type> 
  </address_component> 
  <address_component> 
   <long_name>Amphitheatre Pkwy</long_name> 
   <short_name>Amphitheatre Pkwy</short_name> 
   <type>route</type> 
  </address_component>
  ....
  <geometry> 
   <location> 
    <lat>37.4217550</lat> 
    <lng>-122.0846330</lng> 
   </location> 
   <location_type>ROOFTOP</location_type> 
   <viewport> 
    <southwest> 
     <lat>37.4188514</lat> 
     <lng>-122.0874526</lng> 
    </southwest> 
    <northeast> 
     <lat>37.4251466</lat> 
     <lng>-122.0811574</lng> 
    </northeast> 
   </viewport> 
  </geometry> 
 </result> 
</GeocodeResponse>

И следующий объект

[DataContract(Namespace = "")]
public class GeocodeResponse
{
    [DataMember(Name = "status", Order = 1)]
    public string Status { get; set; }

    [DataMember(Name = "result", Order = 2)]
    public List<Result> Results { get; set; }

    [DataContract(Name = "result", Namespace = "")]
    public class Result
    {
        [DataMember(Name = "geometry")]
        public CGeometry Geometry { get; set; }

        [DataContract(Name = "geometry", Namespace = "")]
        public class CGeometry
        {
            [DataMember(Name = "location")]
            public CLocation Location { get; set; }

            [DataContract(Name = "location", Namespace = "")]
            public class CLocation
            {
                [DataMember(Name = "lat", Order = 1)]
                public double Lat { get; set; }
                [DataMember(Name = "lng", Order = 2)]
                public double Lng { get; set; }
            }
        }
    }
}

Я пытаюсь десериализовать, используя следующий метод

DataContractSerializer serializer = new DataContractSerializer(typeof(GeocodeResponse));

var response = (GeocodeResponse)serializer.ReadObject(request.GetResponse().GetResponseStream());

После десериализации результаты всегда пустые.Что я делаю неправильно?

ОБНОВЛЕНИЕ:

Изменен элемент результата.Получаем еще одну ошибку сейчас:

Произошла ошибка десериализации объекта типа GeocodeResponse.Данные на корневом уровне неверны.Строка 1, позиция 1.

...

    [DataMember(Name = "result", Order = 2)]
    public CResult Result { get; set; }

    [DataContract]
    public class CResult
    {
    ...

Я могу десериализовать исходный объект, используя JSON, как показано ниже.

DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(GeocodeResponse));

Ответы [ 2 ]

2 голосов
/ 27 сентября 2011

Вы не можете использовать DataContractSerializer (DCS) для десериализации ответа на этот запрос, вам нужно использовать XmlSerializer. DCS не поддерживает развернутые коллекции, что и содержится в ответе - как показано ниже.

<a>
  <b/>
  <c/>
  <c/>
  <c/>
</a>

DCS поддерживает коллекции только тогда, когда они заключены в свой собственный элемент:

<a>
  <b/>
  <cs>
    <c/>
    <c/>
    <c/>
  </cs>
</a>

XmlSerializer поддерживает такие коллекции. Приведенный ниже код демонстрирует частичную структуру классов для десериализации ответа из XML-кода геокодирования Google.

public class StackOverflow_7521821
{
    [XmlRoot(ElementName = "GeocodeResponse", Namespace = "")]
    public class GeocodeResponse
    {
        [XmlElement(ElementName = "status")]
        public GeocodeResponseStatusCode Status;
        [XmlElement(ElementName = "result")]
        public List<GeocodeResponseResult> Results;
    }
    [XmlType(Namespace = "")]
    public class GeocodeResponseResult
    {
        [XmlElement(ElementName = "type")]
        public List<string> Types;
        [XmlElement(ElementName = "formatted_address")]
        public string FormattedAddress;
        [XmlElement(ElementName = "address_component")]
        public List<GeocodeResponseAddressComponent> AddressComponents;
        [XmlElement(ElementName = "geometry")]
        public GeocodeResponseResultGeometry Geometry;
    }
    [XmlType(Namespace = "")]
    public class GeocodeResponseAddressComponent
    {
        [XmlElement(ElementName = "long_name")]
        public string LongName;
        [XmlElement(ElementName = "short_name")]
        public string ShortName;
        [XmlElement(ElementName = "type")]
        public List<string> Types;
    }
    [XmlType(Namespace = "")]
    public class GeocodeResponseResultGeometry
    {
        [XmlElement(ElementName = "location")]
        public Location Location;
        [XmlElement(ElementName = "location_type")]
        public GeocodeResponseResultGeometryLocationType LocationType;
        [XmlElement(ElementName = "viewport")]
        public GeocodeResponseResultGeometryViewport Viewport;
    }
    [XmlType(Namespace = "")]
    public class GeocodeResponseResultGeometryViewport
    {
        [XmlElement(ElementName = "southwest")]
        public Location Southwest;
        [XmlElement(ElementName = "northeast")]
        public Location Northeast;
    }
    public enum GeocodeResponseStatusCode
    {
        OK, 
        ZERO_RESULTS, 
        OVER_QUERY_LIMIT, 
        REQUEST_DENIED, 
        INVALID_REQUEST,
    }
    public enum GeocodeResponseResultGeometryLocationType
    {
        ROOFTOP,
        RANGE_INTERPOLATED,
        GEOMETRIC_CENTER,
        APPROXIMATE,
    }
    [XmlType(Namespace = "")]
    public class Location
    {
        [XmlElement(ElementName = "lat")]
        public string Lat;
        [XmlElement(ElementName = "lng")]
        public string Lng;
    }
    public static void Test()
    {
        XmlSerializer xs = new XmlSerializer(typeof(GeocodeResponse));
        WebClient c = new WebClient();
        byte[] response = c.DownloadData("http://maps.googleapis.com/maps/api/geocode/xml?address=1+Microsoft+Way,+Redmond,+WA&sensor=true");
        MemoryStream ms = new MemoryStream(response);
        GeocodeResponse geocodeResponse = (GeocodeResponse)xs.Deserialize(ms);
        Console.WriteLine(geocodeResponse);

        c = new WebClient();
        response = c.DownloadData("http://maps.googleapis.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true");
        ms = new MemoryStream(response);
        geocodeResponse = (GeocodeResponse)xs.Deserialize(ms);
        Console.WriteLine(geocodeResponse);
    }
}
0 голосов
/ 23 сентября 2011

Вы не хотите использовать List<Result>, если есть только один тег <result> со всем внутри него.Я удалил List из своего тестового кода, и он Results больше не пуст.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...