2

I'm trying to return to separate string in this if statement and not as a single string. one as a latitude and the other as longitude

static string GeoCoding(string address)
{
    var json = new WebClient().DownloadString(baseUrlGC + address.Replace(" ", "+")
        + plusUrl);//concatenate URL with the input address and downloads the requested resource
    GoogleGeoCodeResponse jsonResult = JsonConvert.DeserializeObject<GoogleGeoCodeResponse>(json); //deserializing the result to GoogleGeoCodeResponse

    string status = jsonResult.status; // get status 

    string geoLocation = String.Empty;

    //check if status is OK
    if (status == "OK") 
    {
        
        for (int i = 0; i < jsonResult.results.Length;i++) //loop throught the result for lat/lng
        {
            geoLocation = jsonResult.results[i].geometry.location.lat + jsonResult.results[i].geometry.location.lng + Environment.NewLine; //append the result addresses to every new line
        }
        return geoLocation; //return result
    }
    else
    {
        return status; //return status / error if not OK
    }
}
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
  • What exactly is your question? – Peter Csala Oct 05 '22 at 09:16
  • 3
    Your loop assigns a brand new value to `geoLocation` every time so you'll only get the last string. Perhaps you wanted `geoLocation = geoLocation + ...` – paddy Oct 05 '22 at 09:17
  • @PeterCsala I'm to separate into two and return each value differently. Eg Latitude = jsonResult.results[i].geometry.location.lat and Longitude = jsonResult.results[i].geometry.location.lng –  Oct 05 '22 at 09:21
  • Does this answer your question? [parse google maps geocode json response to object using Json.Net](https://stackoverflow.com/questions/3001132/parse-google-maps-geocode-json-response-to-object-using-json-net) – Neil Oct 05 '22 at 09:22
  • 1
    Then change the signature to return a `ValueTuple`: `static (string Latitude, string Longitude) GeoCoding(string address)` and change the `return` statements as well accordingly. – Peter Csala Oct 05 '22 at 09:27
  • The old way would be to create a class or struct with properties for latitude and longitude and return that. But maybe you would like to return it as a JSON-string? You could serialize the class or struct to JSON in that case. But a newer way would be to return a tuple: (string long, string lat) GeoCoding(string address) – Svein Terje Gaup Oct 05 '22 at 09:27
  • @PeterCsala do you mind doing it because I am a bit confused –  Oct 05 '22 at 09:40
  • @Musty Do you want to return a single lat-long pair or do you need all lat-long pairs? If the status code is not okay then is it fine from requirement perspective to throw an exception? – Peter Csala Oct 05 '22 at 10:07
  • @PeterCsala i want all lat-long pairs –  Oct 05 '22 at 10:29

2 Answers2

0

Assuming your expected result is 2 string: Latitude Longitude and a code when there is error. I would suggest you create a new

class GeoResponse{
List<(string, string)> geocodeList;
string  status;
} 

and change return type of your method to

static GeoResponse GeoCoding(string address)
        {
            var json = new WebClient().DownloadString(baseUrlGC + address.Replace(" ", "+")
                + plusUrl);//concatenate URL with the input address and downloads the requested resource
            GoogleGeoCodeResponse jsonResult = JsonConvert.DeserializeObject<GoogleGeoCodeResponse>(json); //deserializing the result to GoogleGeoCodeResponse

           

            GeoResponse result = new GeoResponse();
            result.status = jsonResult.status; // get status 

            //check if status is OK
            if (status == "OK")
            {

                for (int i = 0; i < jsonResult.results.Length; i++) //loop throught the result for lat/lng
                {
                    result.geocodeList.Add(jsonResult.results[i].geometry.location.lat, jsonResult.results[i].geometry.location.lng);
                }
            }
            return result;
        }
hieu.do
  • 61
  • 1
  • 9
0

If you would like to return with all lat-long pairs (without creating a new data structure) when status is ok and throw an exception when status was not ok then you can do that like this:

static List<Tuple<string, string>> GeoCoding(string address)
{
    var json = new WebClient().DownloadString($"...");
    var jsonResult = JsonConvert.DeserializeObject<GoogleGeoCodeResponse>(json); 

    if (jsonResult.status != "OK")
        throw new Exception($"Request failed with {jsonResult.status}");

    return jsonResult.results
        .Select(result => result.geometry.location)
        .Select(loc => new Tuple<string, string>(loc.lat, loc.lng))
        .ToList();
}

If you can use ValueTuple then you could rewrite the code like this:

static List<(string Lat, string Long)> GeoCoding(string address)
{
    ...

    return jsonResult.results
        .Select(result => result.geometry.location)
        .Select(loc => (loc.lat, loc.lng))
        .ToList();
}

Please also note that WebClient is deprecated so please prefer HttpClient instead.


UPDATE #1

I want to output "N/A" for the ZERO_RESULTS

static List<(string Lat, string Long)> GeoCoding(string address)
{
    var json = new WebClient().DownloadString($"...");
    var jsonResult = JsonConvert.DeserializeObject<GoogleGeoCodeResponse>(json); 

    if (jsonResult.status == "ZERO_RESULTS")
        return new List<(string, string)> { ("N/A", "N/A") };

    if (jsonResult.status != "OK")
        throw new Exception($"Request failed with {jsonResult.status}");

    return jsonResult.results
        .Select(result => result.geometry.location)
        .Select(loc => (loc.lat, loc.lng))
        .ToList();
}
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
  • It works perfectly but the problem is that there's an exception unhandled error saying "System.Exception: 'Request failed with ZERO_RESULTS' " –  Oct 05 '22 at 11:16
  • @Musty You should receive that exception only if the parsed json's `status` contains different string than `"OK"`. If `ZERO_RESULTS` should be treated as an empty list then you should code that inside the `GeoCoding` method. – Peter Csala Oct 05 '22 at 11:25
  • Yes i want to output "N/A" for the ZERO_RESULTS. Should i use an if statement for it. similar to the ok statement? –  Oct 05 '22 at 12:23
  • @Musty Yes, you can handle that with branching. – Peter Csala Oct 05 '22 at 13:08
  • I tried the branching but i am still getting the same error –  Oct 05 '22 at 13:22
  • @Musty Let me amend my post to include this as well. – Peter Csala Oct 05 '22 at 13:35
  • @Musty I've just did it, please check it! – Peter Csala Oct 05 '22 at 13:44
  • I used the WebClient so i get an error –  Oct 05 '22 at 13:57
  • @Musty I'm not sure what do mean. The IDE warns you that it is deprecated, but that's just a warning not error (unless you specified your project to [treat warnings as error](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/errors-warnings)) – Peter Csala Oct 05 '22 at 14:18
  • I can't run the program because I get an error not warning –  Oct 05 '22 at 14:24
  • @Musty What error do you receive? – Peter Csala Oct 05 '22 at 14:34
  • error CS0029: Cannot implicitly convert type 'System.Collections.Generic.List<(string, string)>' to 'System.Collections.Generic.List> –  Oct 05 '22 at 14:42
  • @Musty I think you are mixing the two proposed solutions. If you are using `Tuple` not `ValueTuple` then the *update #1* should use this code: `return new List> { new Tuple("N/A", "N/A") };` – Peter Csala Oct 05 '22 at 14:50
  • Yes I was mixing it up. I tried your new solution but it prints out nothing –  Oct 05 '22 at 15:13
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/248570/discussion-between-peter-csala-and-musty). – Peter Csala Oct 05 '22 at 15:14