Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse JSON code from Bing Map API in C#

Tags:

json

c#

bing-maps

I use Bing Map REST API, because i want to find out the geolocation from a secific location. The Url works great, but due to the fact, i use JSON code the first time, i dont really know how i get the output i want.

I tried the following:

string URL = "http://dev.virtualearth.net/REST/v1/Locations?countryRegion=&adminDistrict=&locality=Wien&postalCode=&addressLine=&userLocation=&userIp=&usermapView=&includeNeighborhood=&maxResults=&key=MY_KEY";
WebClient client = new WebClient();
client.OpenReadAsync(new Uri(URL, UriKind.Absolute));
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);

private void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Point));
    Point data = serializer.ReadObject(e.Result) as Point;
}

[DataContract]
public class Point
{
    /// <summary>
    /// Latitude,Longitude
    /// </summary>
    [DataMember(Name = "coordinates")]
    public double[] Coordinates { get; set; }
}

When I type the link in the browser, this is my response:

{"authenticationResultCode":"ValidCredentials","brandLogoUri":"http://dev.virtualearth.net/Branding/logo_powered_by.png","copyright":"Copyright © 2013 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.","resourceSets":[{"estimatedTotal":1,"resources":[{"__type":"Location:http://schemas.microsoft.com/search/local/ws/rest/v1","bbox":[47.253395080566406,-123.16571807861328,47.946159362792969,-121.50344085693359],"name":"Seattle, WA","point":{"type":"Point","coordinates":[47.603561401367188,-122.32943725585938]},"address":{"adminDistrict":"WA","adminDistrict2":"King Co.","countryRegion":"United States","formattedAddress":"Seattle, WA","locality":"Seattle"},"confidence":"High","entityType":"PopulatedPlace","geocodePoints":[{"type":"Point","coordinates":[47.603561401367188,-122.32943725585938],"calculationMethod":"Rooftop","usageTypes":["Display"]}],"matchCodes":["Good"]}]}],"statusCode":200,"statusDescription":"OK","traceId":"08bee37ecb714d7cb7e2783eb8f873a4|LTSM000177|02.00.183.2300|LTSIPEVM000039"}

My Question now is: is this the correct way to do it? And how do i get the data?

I hope you can help me, I already spent a lot of time with this problem.

-----EDIT-----

Now i use JSON.net, but i dont know, how to parse the data i get from the Website to a string variable.

I tried the following:

var json = new WebClient().DownloadString("url");

but this dont work, because i am developing on Windows Phone.

System.Net.WebClient does not contain a definition for "DownloadString" ...

Anyone can help me to get this working for Windows Phone Apps.

like image 251
Crusader633 Avatar asked Oct 03 '13 17:10

Crusader633


4 Answers

When working with json, I prefer Json.Net. After declaring necessary classes, this code is all

var root = JsonConvert.DeserializeObject<RootObject>(json);

foreach (var rs in root.resourceSets)
{
    foreach (var r in rs.resources)
    {
        Console.WriteLine(r.point.coordinates[0] + " , " + r.point.coordinates[1]);
    }
}

You can use this site to convert your json to concrete classes

public class Point
{
    public string type { get; set; }
    public List<double> coordinates { get; set; }
}

public class Address
{
    public string adminDistrict { get; set; }
    public string adminDistrict2 { get; set; }
    public string countryRegion { get; set; }
    public string formattedAddress { get; set; }
    public string locality { get; set; }
}

public class GeocodePoint
{
    public string type { get; set; }
    public List<double> coordinates { get; set; }
    public string calculationMethod { get; set; }
    public List<string> usageTypes { get; set; }
}

public class Resource
{
    public string __type { get; set; }
    public List<double> bbox { get; set; }
    public string name { get; set; }
    public Point point { get; set; }
    public Address address { get; set; }
    public string confidence { get; set; }
    public string entityType { get; set; }
    public List<GeocodePoint> geocodePoints { get; set; }
    public List<string> matchCodes { get; set; }
}

public class ResourceSet
{
    public int estimatedTotal { get; set; }
    public List<Resource> resources { get; set; }
}

public class RootObject
{
    public string authenticationResultCode { get; set; }
    public string brandLogoUri { get; set; }
    public string copyright { get; set; }
    public List<ResourceSet> resourceSets { get; set; }
    public int statusCode { get; set; }
    public string statusDescription { get; set; }
    public string traceId { get; set; }
}

Json.net also allows you use dynamic keyword without declaring any of these classes.

dynamic root = JsonConvert.DeserializeObject(json);

foreach (var rs in root.resourceSets)
{
    foreach (var r in rs.resources)
    {
        Console.WriteLine(r.point.coordinates[0] + " , " + r.point.coordinates[1]);
    }
}
like image 80
EZI Avatar answered Nov 15 '22 11:11

EZI


You can use the Microsoft JSON serializer/deserializer.

If you're not working with ASP.NET you need to include the System.Web and System.Web.Extensions references;

JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
Dictionary<string, object> json = (object[])javaScriptSerializer.DeserializeObject(text);

You don't need to map it to an set of classes or structures, arrays will be converted to object[] and objects will be converted to Dictionary.

To view the content of the resulting Dictionary json you can use the visual studio inspector or just access directly the content remembering how the elements are mapped.

For example to access the brandLogoUri you just need

(string)json["brandLogoUri"]

To loop the resourceSets, that is an array, you need to do the following

foreach(Dictionary<string,object> key in (Dictionary<string,object>)json["resourceSets"])
{
...do your stuff here...
}

Obiviously your code will be less readable, but it is useful if it is too difficult to map the json to classes or if you want to do some tests on the fly

like image 32
Daniele Salvatore Albano Avatar answered Nov 15 '22 11:11

Daniele Salvatore Albano


You can use http://json2csharp.com/ to generate a custom class. Include it on project code. After, use the same DataContractJsonSerializer with the new CustomClass.

DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(CustomClass));
CustomClass data = serializer.ReadObject(e.Result);

If you use VS2012 you have a Tools : http://blogs.msdn.com/b/webdev/archive/2012/12/18/paste-json-as-classes-in-asp-net-and-web-tools-2012-2-rc.aspx

like image 33
tdelepine Avatar answered Nov 15 '22 13:11

tdelepine


I KNOW YOU ARE USING BING MAPS, But here is a google solution aswell:

Google Map API request and parse DirectionsResponse with C#, change the json in your url to xml and use the following code to turn the result into a usable C# Generic List Object.

var url = String.Format("http://maps.googleapis.com/maps/api/directions/xml?...");
var result = new System.Net.WebClient().DownloadString(url);
var doc = XDocument.Load(new StringReader(result));

var DirectionsResponse = doc.Elements("DirectionsResponse").Select(l => new
{
    Status = l.Elements("status").Select(q => q.Value).FirstOrDefault(),
    Route = l.Descendants("route").Select(n => new
    {
        Summary = n.Elements("summary").Select(q => q.Value).FirstOrDefault(),
        Leg = n.Elements("leg").ToList().Select(o => new
        {
            Step = o.Elements("step").Select(p => new
            {
                Travel_Mode = p.Elements("travel_mode").Select(q => q.Value).FirstOrDefault(),
                Start_Location = p.Elements("start_location").Select(q => new
                {
                    Lat = q.Elements("lat").Select(r => r.Value).FirstOrDefault(),
                    Lng = q.Elements("lng").Select(r => r.Value).FirstOrDefault()
                }).FirstOrDefault(),
                End_Location = p.Elements("end_location").Select(q => new
                {
                    Lat = q.Elements("lat").Select(r => r.Value).FirstOrDefault(),
                    Lng = q.Elements("lng").Select(r => r.Value).FirstOrDefault()
                }).FirstOrDefault(),
                Polyline = p.Elements("polyline").Select(q => new
                {
                    Points = q.Elements("points").Select(r => r.Value).FirstOrDefault()
                }).FirstOrDefault(),
                Duration = p.Elements("duration").Select(q => new
                {
                    Value = q.Elements("value").Select(r => r.Value).FirstOrDefault(),
                    Text = q.Elements("text").Select(r => r.Value).FirstOrDefault(),
                }).FirstOrDefault(),
                Html_Instructions = p.Elements("html_instructions").Select(q => q.Value).FirstOrDefault(),
                Distance = p.Elements("distance").Select(q => new
                {
                    Value = q.Elements("value").Select(r => r.Value).FirstOrDefault(),
                    Text = q.Elements("text").Select(r => r.Value).FirstOrDefault(),
                }).FirstOrDefault()
            }).ToList(),
            Duration = o.Elements("duration").Select(p => new
            {
                Value = p.Elements("value").Select(q => q.Value).FirstOrDefault(),
                Text = p.Elements("text").Select(q => q.Value).FirstOrDefault()
            }).FirstOrDefault(),
            Distance = o.Elements("distance").Select(p => new
            {
                Value = p.Elements("value").Select(q => q.Value).FirstOrDefault(),
                Text = p.Elements("text").Select(q => q.Value).FirstOrDefault()
            }).FirstOrDefault(),
            Start_Location = o.Elements("start_location").Select(p => new
            {
                Lat = p.Elements("lat").Select(q => q.Value).FirstOrDefault(),
                Lng = p.Elements("lng").Select(q => q.Value).FirstOrDefault()
            }).FirstOrDefault(),
            End_Location = o.Elements("end_location").Select(p => new
            {
                Lat = p.Elements("lat").Select(q => q.Value).FirstOrDefault(),
                Lng = p.Elements("lng").Select(q => q.Value).FirstOrDefault()
            }).FirstOrDefault(),
            Start_Address = o.Elements("start_address").Select(q => q.Value).FirstOrDefault(),
            End_Address = o.Elements("end_address").Select(q => q.Value).FirstOrDefault()
        }).ToList(),
        Copyrights = n.Elements("copyrights").Select(q => q.Value).FirstOrDefault(),
        Overview_polyline = n.Elements("overview_polyline").Select(q => new
        {
            Points = q.Elements("points").Select(r => r.Value).FirstOrDefault()
        }).FirstOrDefault(),
        Waypoint_Index = n.Elements("waypoint_index").Select(o => o.Value).ToList(),
        Bounds = n.Elements("bounds").Select(q => new
        {
            SouthWest = q.Elements("southwest").Select(r => new
            {
                Lat = r.Elements("lat").Select(s => s.Value).FirstOrDefault(),
                Lng = r.Elements("lng").Select(s => s.Value).FirstOrDefault()
            }).FirstOrDefault(),
            NorthEast = q.Elements("northeast").Select(r => new
            {
                Lat = r.Elements("lat").Select(s => s.Value).FirstOrDefault(),
                Lng = r.Elements("lng").Select(s => s.Value).FirstOrDefault()
            }).FirstOrDefault(),
        }).FirstOrDefault()
    }).FirstOrDefault()
}).FirstOrDefault();

I hope this will help someone.

like image 33
Pierre Avatar answered Nov 15 '22 13:11

Pierre