Link to home
Start Free TrialLog in
Avatar of ITsolutionWizard
ITsolutionWizardFlag for United States of America

asked on

read Json in c#

I use api.ipstack.com for free and I love it.
When I click on the url, I get the data starting { }.
Can you show me how to read it in c# in a loop? for example, ip: xxx <br> type: ipv6 and etc.


http://api.ipstack.com/check?access_key=36e3590e1bc049471958186382dc1asdfdae58asdfasdfasd

{"ip":"2603:8000:1101:425:f9ba:86c1:fed4:8136","type":"ipv6","continent_code":"NA","continent_name":"North America","country_code":"US","country_name":"United States","region_code":"CO","region_name":"Colorado","city":"Centennial","zip":"80111","latitude":39.64134343688659668,"longitude":-104.9545832984375,"location":{"geoname_id":5416541,"capital":"Washington D.C.","languages":[{"code":"en","name":"English","native":"English"}],"country_flag":"http:\/\/assets.ipstack.com\/flags\/us.svg","country_flag_emoji":"\ud83c\uddfa\ud83c\uddf8","country_flag_emoji_unicode":"U+1F1FA U+1F1F8","calling_code":"1","is_eu":false}}
Avatar of ITsolutionWizard
ITsolutionWizard
Flag of United States of America image

ASKER

help?
have a look at this

https://dotnetfiddle.net/uUPqCR

using System;
using Newtonsoft.Json;

public class Program
{
   public static void Main()
   {
      String jsonStr = @"{'ip':'2603:8000:1101:425:f9ba:86c1:fed4:8136','type':'ipv6','continent_code':'NA','continent_name':'North America','country_code':'US','country_name':'United States','region_code':'CO','region_name':'Colorado','city':'Centennial','zip':'80111','latitude':39.64134343688659668,'longitude':-104.9545832984375,'location':{'geoname_id':5416541,'capital':'Washington D.C.','languages':[{'code':'en','name':'English','native':'English'},{'code':'fr','name':'French','native':'Frencaise'},{'code':'TR','name':'Turkish','native':'Turkish'}],'country_flag':'http:\\assets.ipstack.com\flags\\us.svg','country_flag_emoji':'\ud83c\uddfa\ud83c\uddf8','country_flag_emoji_unicode':'U+1F1FA U+1F1F8','calling_code':'1','is_eu':false}}";
      dynamic json = JsonConvert.DeserializeObject(jsonStr);
      Console.WriteLine(json.ip);
      Console.WriteLine(json.location.languages[0].code);
      foreach (dynamic lng in json.location.languages)
      {
         Console.WriteLine("Language...");
         Console.WriteLine("Code = " + lng.code);
         Console.WriteLine("Name = " + lng.name);
         Console.WriteLine("Native = " + lng.native);
      }
   }
}

Open in new window

result
2603:8000:1101:425:f9ba:86c1:fed4:8136
en
Language...
Code = en
Name = English
Native = English
Language...
Code = fr
Name = French
Native = Frencaise
Language...
Code = TR
Name = Turkish
Native = Turkish

Open in new window

Avatar of gr8gonzo
First, I would suggest editing your comment and redacting your access key.

Second, if you're looking for general advice, you can either use the JavascriptSerializer (https://docs.microsoft.com/en-us/dotnet/api/system.web.script.serialization.javascriptserializer?view=netframework-4.8) class that's out of the box or your can install JSON.NET (https://www.newtonsoft.com/json).

I find that JSON.NET is a little better at error-handling than the Microsoft classes, but it means packaging another DLL with your application.

If you want more explicit examples, you'll need to share your current code.

EDIT: HainKurt's suggestion (added while I write up mine) is also a good one. 
I prefer explicit deserialization to DTO's. E.g.

namespace ConsoleCS
{
    using System;
    using Newtonsoft.Json;

    public static class Program
    {
        public static void Main(string[] args)
        {
            string response = @"{'ip':'2603:8000:1101:425:f9ba:86c1:fed4:8136','type':'ipv6','continent_code':'NA','continent_name':'North America','country_code':'US','country_name':'United States','region_code':'CO','region_name':'Colorado','city':'Centennial','zip':'80111','latitude':39.64134343688659668,'longitude':-104.9545832984375,'location':{'geoname_id':5416541,'capital':'Washington D.C.','languages':[{'code':'en','name':'English','native':'English'},{'code':'fr','name':'French','native':'Frencaise'},{'code':'TR','name':'Turkish','native':'Turkish'}],'country_flag':'http:\\assets.ipstack.com\flags\\us.svg','country_flag_emoji':'\ud83c\uddfa\ud83c\uddf8','country_flag_emoji_unicode':'U+1F1FA U+1F1F8','calling_code':'1','is_eu':false}}";
            IPStackResponse responseObject = JsonConvert.DeserializeObject<IPStackResponse>(response);
            Console.WriteLine(responseObject);
            Console.WriteLine(responseObject.location);
            foreach (Language lng in responseObject.location.languages)
            {
                Console.WriteLine(lng);
            }

            Console.WriteLine("\nDone.");
            Console.ReadLine();
        }
    }

    public class IPStackResponse
    {
        public string ip { get; set; }
        public string type { get; set; }
        public string continent_code { get; set; }
        public string continent_name { get; set; }
        public string country_code { get; set; }
        public string country_name { get; set; }
        public string region_code { get; set; }
        public string region_name { get; set; }
        public string city { get; set; }
        public string zip { get; set; }
        public float latitude { get; set; }
        public float longitude { get; set; }
        public Location location { get; set; }
        public override string ToString() { return $"{ip} : {city} ({continent_name} - {country_name} - {region_name})"; }
    }

    public class Location
    {
        public int geoname_id { get; set; }
        public string capital { get; set; }
        public Language[] languages { get; set; }
        public string country_flag { get; set; }
        public string country_flag_emoji { get; set; }
        public string country_flag_emoji_unicode { get; set; }
        public string calling_code { get; set; }
        public bool is_eu { get; set; }
        public override string ToString() { return $"{geoname_id} : {capital} ({country_flag}, {is_eu})"; }
    }

    public class Language
    {
        public string Code { get; set; }
        public string Name { get; set; }
        public string Native { get; set; }
        public override string ToString() { return $"{Code} : {Name} ({Native})"; }
    }
}

Open in new window

Depending on the use-case having DTO's makes life easier, as you can code e.g. your repository against them instead of using additional adapters, strategies or factories.
Thank you so much. but the codes doe not work because it has "" "" not ' ' that you guys posted. what should I do?


{"ip":"2603:8000:1101:425:f9ba:86c1:fed4:8136","type":"ipv6","continent_code":"NA","continent_name":"North America","country_code":"US","country_name":"United States","region_code":"CO","region_name":"Colorado","city":"Centennial","zip":"80111","latitude":39.64134343688659668,"longitude":-104.9545832984375,"location":{"geoname_id":5416541,"capital":"Washington D.C.","languages":[{"code":"en","name":"English","native":"English"}],"country_flag":"http:\/\/assets.ipstack.com\/flags\/us.svg","country_flag_emoji":"\ud83c\uddfa\ud83c\uddf8","country_flag_emoji_unicode":"U+1F1FA U+1F1F8","calling_code":"1","is_eu":false}}
You shouldn't be dealing with the " or ' characters directly. The previous examples were simply hard-coding your string for example purposes and used single quotes so they wouldn't have to escape a ton of double quotes like this:

string response = @"{\"ip\" :\"2603:8000:1101:425:f9ba:86c1:fed4:8136\",\"type\":\"ipv6\",\"continent_code\":\"NA\",....etc...}}";              

Open in new window


In practice, you'll just be dealing with a string that has come back from an API call. The mechanisms mentioned (JsonConvert = JSON.NET or the JavascriptSerializer) will handle quotes appropriately.
And on a side note, I also agree with ste5an that deserializing to a specific class is typically better. It means you have to write more code (defining your classes), but it's less prone to typos/errors and works better with MVVM architecture.

It's like receiving a delivery of food that you ordered. The dynamic method is more like, "Hey, man, just give me the bag of food and I'll look through it later." Then later someone says, "Hey, does the order contain potatoes?" And they have to rifle through the contents of the bag and say, "Um, doesn't look like it."

The explicit deserialization is like saying, "I know this order should contain chicken, potatoes, and carrots. Here is a box with one side reserved for chicken, the middle is reserved for potatoes, and the other side is reserved for carrots, so put them in those specific locations within the box." Any other code that wants to access the potatoes knows exactly where to look in the box and can reference the potatoes very easily because everyone understands where the potatoes should be.

Both methods allow you to do error-checking and stuff like that, but explicit deserialization is simply a little more organized and less susceptible to typos. In the dynamic scenario, you could write code that said, "Give me the potatos" (misspelled) and your code would compile perfectly fine but would fail later when running. In the explicit deserialization scenario, if you wrote, "Give me the potatos", the compiler would warn you that there is no field called "potatos" and you could correct it to "Give me the potatoes." 
Thank you so much. but the codes doe not work because it has "" "" not ' ' that you guys posted. what should I do?

I replaced " with ' and \\ with \ by putting @ in front of it...
because I hardcoded the string...
in your case, you have the string, so no need to do all that stuff, code should work fine as is...

how do you get/set the string?
I do not have the string. The string is generated by http get.

I do not have the string. The string is generated by http get.

so you get and set to a variable...
no need to deal with ' or ""
the code will just work fine with that string...

error msg

Unexpected character encountered while parsing value: h. Path '', line 0, position 0.


Can you provide your code?
string url = "https://api.ipstack.com/check?access_key=36e3590esdfsad1bc04947195818asdfasdf6382dc1e58";
            string jsonStr = (string)JObject.Parse(url);


         
            dynamic json = JsonConvert.DeserializeObject(jsonStr);
            Console.WriteLine(json.ip);
            Console.WriteLine(json.location.languages[0].code);
            foreach (dynamic lng in json.location.languages)
            {
                Console.WriteLine("Language...");
                Console.WriteLine("Code = " + lng.code);
                Console.WriteLine("Name = " + lng.name);
                Console.WriteLine("Native = " + lng.native);
            }

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of HainKurt
HainKurt
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
that is working and it is awesome. Thank.
I use JObject to get individual piece inside of string (result)
In the result, how can I loop it and list all? This is my last question.

Thank you for everyone's time and help.
Thanks,

public void TestMe()
        {
            string url = "http://api.ipstack.com/check?access_key=36e3590e1basdfasdf23432c049471958186382dc1e58";
            String result;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.MaximumAutomaticRedirections = 4;
            request.MaximumResponseHeadersLength = 4;
            request.Credentials = CredentialCache.DefaultCredentials;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream receiveStream = response.GetResponseStream();
            StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
            result = readStream.ReadToEnd();            
            JObject obj = JObject.Parse(result);
            response.Close();
            readStream.Close();
            Response.Write(result + "<br>" + obj.GetValue("ip"));
        }

Open in new window

all the sample codes are in my first post