0

I'm getting JSON from an API, each domain like Google, and Facebook will be dynamic. I'm struggling to access the JSON to then put on a webpage, normally APIs are no issue, but the fact its dynamic is causing problems. Furthermore, no solution on StackOverflow is solving my problem. I've already tried this solution, but unfortunately, it didn't work.

So an example response

{
  "data": {
    "google.com": {
      "domain_authority": 95,
      "page_authority": 88,
      "spam_score": 1,
      "nofollow_links": 76221395,
      "dofollow_links": 465226564
    },
    "facebook.com": {
      "domain_authority": 96,
      "page_authority": 100,
      "spam_score": 1,
      "nofollow_links": 97570534,
      "dofollow_links": 565869181
    },
    "wikipedia.org": {
      "domain_authority": 90,
      "page_authority": 75,
      "spam_score": 1,
      "nofollow_links": 1897582,
      "dofollow_links": 20437023
    }
  }
}

My code to get the value of Google from the example response:

IRestResponse response = client.Execute(request);
// response.Content returns the JSON

var w = new JavaScriptSerializer().Deserialize<Rootobject>(response.Content);

//trying to echo out Google's Domain Authority.
Response.Write(w.data[0].domain_authority);


public class Rootobject
    {

        public Data data { get; set; }
    }

    public class Data
    {
        public int domain_authority { get; set; }
        public int page_authority { get; set; }
        public int spam_score { get; set; }
        public int nofollow_links { get; set; }
        public int dofollow_links { get; set; }
    }

Latest attempt (working although I cannot get the domains names via JSON):

    IRestResponse response = client.Execute(request);


    var root = JsonConvert.DeserializeObject<Rootobject>(response.Content);

    var json2 = JsonConvert.SerializeObject(root, Newtonsoft.Json.Formatting.Indented);

    var list = root.data.Values;


    int c = 1;
    foreach (var domains in list)
    {
        Response.Write(" "+c+":" + domains.domain_authority);
        c++;
    }

public class Rootobject
{
    public Dictionary<string, Data> data { get; set; }
}


public class Data
{
    public int domain_authority { get; set; }
    public int page_authority { get; set; }
    public int spam_score { get; set; }
    public int nofollow_links { get; set; }
    public int dofollow_links { get; set; }
}

Neither of the following work -- and I have a feeling I'm being silly (relatively new to C#, so sorry if it's obvious).

MattHodson
  • 736
  • 7
  • 22
  • Use a dictionary: `public Dictionary data { get; set; }` as shown in [How can I parse a JSON string that would cause illegal C# identifiers?](https://stackoverflow.com/a/24536564/3744182) or [Deserializing JSON when key values are unknown](https://stackoverflow.com/a/24901245/3744182) or [Deserializing JSON with unknown object names](https://stackoverflow.com/q/38688570/3744182) or [Parsing JSON Object with variable properties into strongly typed object](https://stackoverflow.com/q/34202496/3744182). – dbc Apr 16 '20 at 23:21
  • Also, `JavaScriptSerializer` is deprecated, consider upgrading to [tag:json.net] or [tag:system.text.json]. – dbc Apr 16 '20 at 23:22
  • @dbc, thank you for your suggestions. I gave `var w = JsonConvert.DeserializeObject>(response.Content);` a try, and although it didn't fall over, no values were returned at all. – MattHodson Apr 16 '20 at 23:42
  • You need to make the dictionary be a property of your root object: `public class Rootobject { public Dictionary data { get; set; } }`. Then deserialize the root object as you are currently. Demo fiddle: https://dotnetfiddle.net/oFgVH2 – dbc Apr 16 '20 at 23:50
  • Still isn't working, this is what I'm seeing: https://gyazo.com/c0e125cd8f8df24e118ac63ec7eb16b3 – MattHodson Apr 16 '20 at 23:57
  • Can't see it, seems to require tracking cookies that I have blocked. Can you [edit] your question to include an updated [mcve]? Also, take a look at the demo fiddle I included in my previous comment, which deserializes and re-serializes your JSON successfully. The demo fiddle uses Json.NET but the same data model should work with `JavaScriptSerializer`. – dbc Apr 17 '20 at 00:00
  • @dbc, I've updated my question. Just taking a look at your dotnetfiddle & trying to understand it now. :) – MattHodson Apr 17 '20 at 00:08
  • You're still trying to deserialize to a dictionary as your root object rather than trying to deserialize `Rootobject`. – dbc Apr 17 '20 at 00:14
  • @dbc, I looked at your dotfiddle and put the pieces together. I'm 99% there, now, instead of doing `{0}` to display a number for each result, how would I get the domains name for each result? As this doesn't seem to be an option? – MattHodson Apr 17 '20 at 00:45
  • Also, I have updated my question to reflect this near-win! – MattHodson Apr 17 '20 at 00:47
  • The dictionary keys are the domain names. See: [What is the best way to iterate over a dictionary?](https://stackoverflow.com/a/141105/3744182). – dbc Apr 17 '20 at 00:48
  • If you'd like to upload your dotfiddle as an answer, I will happily accept it. Very happy indeed, thank you! – MattHodson Apr 17 '20 at 01:01

1 Answers1

0

Unless you specifically want an object, leaving it as a JsonDocument is likely an easier and more flexible solution.

//using System.Text.Json;

JsonDocument document = JsonDocument.Parse(@"{  ""data"" : { ""google.com"" : { ""domain_authority"" : 95 }  , ""facebook.com"" : { ""domain_authority"" : 76 }  } }");

JsonElement root = document.RootElement;
JsonElement data = root.GetProperty("data");
foreach (var domain in data.EnumerateObject())
{
  Console.WriteLine($"got domain {domain.Name}, auth {domain.Value.GetProperty("domain_authority")}");
}

creates output:

got domain google.com, auth 95
got domain facebook.com, auth 76
Richard
  • 603
  • 3
  • 14