0

Im trying to parse a http web response into an array or something so i can work with the information. This is the json response i get (+ a lot more, but i just censored the format):

{
    "meta": {
        "status": 200
    },
    "data": {
        "account": {
            "account_phone_number": "XXXXXXXX",
            "account_email": "MAIL@hotmail.com"
        },
        "user": {
            "id": "5f2b17e7836fc7010025aed3",
            "age": 23,
        }
    }
}

How can i write the "id" inside of "user" to console or a textbox?

This is my web request:

private void button1_Click(object sender, EventArgs e)
{
    const string WEBSERVICE_URL = "url_here";
    try
    {
        var webRequest = System.Net.WebRequest.Create(WEBSERVICE_URL);
        if (webRequest != null)
        {
            webRequest.Method = "GET";
            webRequest.Timeout = 12000;
            webRequest.ContentType = "application/json";
            webRequest.Headers.Add("x-auth-token", "Auth_token");

            using (System.IO.Stream s = webRequest.GetResponse().GetResponseStream())
            {
                using (System.IO.StreamReader sr = new System.IO.StreamReader(s))
                {
                    var jsonResponse = sr.ReadToEnd();
                    richTextBox1.AppendText(jsonResponse);
                }
            }
        }
    }
    catch (Exception ex)
    {
        richTextBox1.AppendText("No workie");
    }
}

I have tried the following:

public class Test
{
   public string meta {get;set;}
   public string data {get;set;}
}

and trying to serialize the json into a table as following:

JavaScriptSerializer js = new JavaScriptSerializer();
Test[] Tester = js.Deserialize<Test[]>(jsonResponse);
richTextBox1.AppendText(Tester);

But no luck. Can anyone please point me in the right direction here?

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
Asphaug
  • 21
  • 1
  • 7
  • You go to http://quicktype.io and paste your json in there.. It makes classes for you to represent the json and even shows you (in code comments) how to use them. The end – Caius Jard Feb 15 '21 at 09:32
  • @Asphaug Do you need all of the information from the response or only just the `id` of the `user` object? – Peter Csala Feb 15 '21 at 09:36
  • @PeterCsala I know what tags i need, for an example i need both the ```id``` and ```age``` inside ```user```. AND only the ```account_email``` from ```account```. – Asphaug Feb 15 '21 at 09:43
  • @Asphaug Can you use different serializer than `JavaScriptSerializer`? Or is it a constraint that you have to satisfy? – Peter Csala Feb 15 '21 at 09:50
  • @PeterCsala I guess i can do it any way that works. This is just the solution i thought was right. – Asphaug Feb 15 '21 at 09:59
  • `JavaScriptSerializer` isn't recommended to use anymore – Pavel Anikhouski Feb 15 '21 at 14:18

2 Answers2

1

If you are able to use other serializer than JavaScriptSerializer then you can take advantage of partial deserializing.

In case of Json.NET (formerly known as Newtonsoft Json) you have at least two options:

SelectToken

JObject semiParsedData = JObject.Parse(jsonResponse);
string id = (string)semiParsedData.SelectToken("data.user.id");
int age = (int)semiaParsedData.SelectToken("data.user.age");
string email = (string)semiParsedData.SelectToken("data.account.account_email");
  • By calling the Parse method we will have a semi-parsed object.
  • On this object we can issue a Json Path query via the SelectToken.
    • The syntax is similar to XPath, which can be used to retrieve any arbitrary data form an XML.
    • More precisely it is a JPath.
  • SelectToken returns a JToken. From it you can retrieve data in several ways:
    • (string)semiParsedData.SelectToken("data.user.id")
    • semiParsedData.SelectToken("data.user.id").Value<string>()
    • semiParsedData.SelectToken("data.user.id").ToObject<string>()

References:

indexer operator

JObject semiParsedData = JObject.Parse(jsonResponse);
JToken data = semiParsedData["data"];

JToken user = data["user"];
string id = (string)user["id"];
int age = (int)user["age"];

JToken account = data["account"];
string email = (string)account["account_email"];
  • JToken defines the following indexer operator, which is not really useful:
public virtual JToken? this[object key]
{
    get => throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
    set => throw new InvalidOperationException("Cannot set child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
}
  • On the other hand its derived class JObject overrides this to make that functionality useful:
    • (JObject derives from JContainer, which derives from JToken).
public JToken? this[string propertyName]
{
    get
    {
        ValidationUtils.ArgumentNotNull(propertyName, nameof(propertyName));
        JProperty? property = Property(propertyName, StringComparison.Ordinal);
        return property?.Value;
    }
    set
    {
        JProperty? property = Property(propertyName, StringComparison.Ordinal);
        if (property != null)
        {
            property.Value = value!;
        }
        else
        {
#if HAVE_INOTIFY_PROPERTY_CHANGING
            OnPropertyChanging(propertyName);
#endif
            Add(propertyName, value);
            OnPropertyChanged(propertyName);
        }
    }
}
  • Here the Property method tries to get the requested entity from the _properties collection:
    • private readonly JPropertyKeyedCollection _properties

Reference:

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
  • I may be a completely noob right now, but ```Exception thrown: 'System.ArgumentNullException' in Newtonsoft.Json.dll```. ```using (System.IO.StreamReader sr = new System.IO.StreamReader(s)) { var jsonResponse = sr.ReadToEnd(); JObject semiParsedData = JObject.Parse(jsonResponse); JToken data = semiParsedData["data"]; JToken user = data["user"]; string id = (string)user["id"]; int age = (int)user["age"]; JToken account = data["account"]; string email = (string)account["account_email"]; Console.WriteLine(id); }``` – Asphaug Feb 15 '21 at 11:00
  • @Asphaug Could you please debug it to know which line of the above code piece throws the `ArgumentNullException`? – Peter Csala Feb 15 '21 at 11:08
  • ```int age = (int)user["age"];``` ```System.ArgumentNullException: 'Value cannot be null. Arg_ParamName_Name'``` – Asphaug Feb 15 '21 at 11:16
  • 1
    Damn, i misspelled something after censoring it back to the correct format. This actually worked! Now i need to understand whats going on :o Thank you! – Asphaug Feb 15 '21 at 11:19
  • @Asphaug I'm glad that it works. If you wish I can extend my proposed solution with some explanation. – Peter Csala Feb 15 '21 at 11:21
  • 1
    @Asphaug I've extended my answer please check it if you have time. – Peter Csala Feb 15 '21 at 12:20
0

Everything is Correct except your Test Class

For Complex JSON use https://json2csharp.com/ For Converting Json To C# Class

public class Meta    {
    public int status { get; set; } 
}

public class Account    {
    public string account_phone_number { get; set; } 
    public string account_email { get; set; } 
}

public class User    {
    public string id { get; set; } 
    public int age { get; set; } 
}

public class Data    {
    public Account account { get; set; } 
    public User user { get; set; } 
}

public class Root    {
    public Meta meta { get; set; } 
    public Data data { get; set; } 
}

and Then Use This

JavaScriptSerializer js = new JavaScriptSerializer();
var Root = js.Deserialize<Root>(jsonResponse);