I try to make a code to display organisms phylum, order, and kingdom, in lblOrganismIdentity. Firstly, the user must input the species name in the tbNameSpecies. And then click btProcess to run the method on Organism class. And the name is used to make the API link. The API data is in this link for example. I dont know how to make the data to become an array, and then display it to lblOrganismIdentity.

The exception error message is

System.Collections.Generic.KeyNotFoundException: 'The given key was not present in the dictionary.'

The exception error occurs in this code

JsonObject kingdom = (JsonObject)gbifObj["kingdom"];

I'm using RestSharp and SimpleJson for the references. I've tried to search for the solutions, but I didn't get that.

This is the source code.

The GetOrganismList method in Organism.cs class

public static List<string> GetOrganismList(string link)
    {
        List<string> returnList = new List<string>();
        var client = new RestClient(link);
        var request = new RestRequest(Method.GET);
        IRestResponse response = client.Execute(request);
        JsonObject gbifObj = (JsonObject)SimpleJson.SimpleJson.DeserializeObject(response.Content);
        Console.WriteLine(gbifObj); 
        JsonObject kingdom = (JsonObject)gbifObj["kingdom"];
        JsonObject phylum = (JsonObject)gbifObj["phylum"];
        JsonObject order = (JsonObject)gbifObj["order"];
        returnList.Add((string)kingdom["kingdom"]);
        returnList.Add((string)phylum["phylum"]);
        returnList.Add((string)order["order"]);
        return returnList;
    }

Form1.cs

    public Form1()
    {
        InitializeComponent();
    }

    List<string> identityList = new List<string>();
    private IEnumerable<string> identitylist;

    private void btProcess_Click(object sender, EventArgs e)
    {
        DisplayInfo(identityList);

    }

    private void DisplayInfo(List<string> identityList)
    {
        string link = "http://api.gbif.org/v1/species/match?&name=" + tbNameSpecies.Text.ToString();
        identityList = Organism.GetOrganismList(link);
        lblOrganismIdentity.Text = "";
        foreach (string item in identityList)
        {
            lblOrganismIdentity.Text += "- " + item + Environment.NewLine;
        }
    }

I expect the lblOrganismIdentity can display data of the species from the user input. For example:

kingdom: Animalia

phylum: Chordata

order: Carnivora

2 Answers

0
siggi_pop On Best Solutions

I made it work in a simple console app by Deserializing to expected object: notice i displayed value in a console app since i couldn't be bothered to create a new win form:

create a class for the return object. It's more clean.

class Animal {
    public int usageKey { get; set; }
    public int acceptedUsageKey { get; set; }
    public string scientificName { get; set; }
    public string canonicalName { get; set; }
    public string rank { get; set; }
    public string status { get; set; }
    public int confidence { get; set; }
    public string matchType { get; set; }
    public string kingdom { get; set; }
    public string phylum { get; set; }
    public int kingdomKey { get; set; }
    public int phylumKey { get; set; }
    public bool synonym { get; set; }
}

Here is the method to get the value from api and do something with it

async void AsyncToConsole(Uri uri, Action<Animal> action) {

    using (var client = new HttpClient())
    {
        var getReg = await client.GetAsync(uri);
        var json = await getReg.Content.ReadAsStringAsync();                
        Animal animal;
        try
        {
            animal = (SimpleJson.DeserializeObject<Animal>(json));
            action(animal);
        }
        catch (Exception)
        {
            action(new Animal() { kingdom = "error", confidence = 0, phylum = "error" });
        }
    }
}

Main method, kinda like your form click event handler

static void Main(string[] args)
{
    var species = "Lycopodiophyta";
    var uri = new Uri($"http://api.gbif.org/v1/species/match?&name={ species }");

    // callable method to display the values. like your foreach loop
    // it will be passed to the async method, who will then call it instead.
    Action<Animal> populateLabel = (Animal animal) =>
    {
        Console.WriteLine($"- {animal.kingdom}");
        Console.WriteLine($"- {animal.phylum}");
        Console.WriteLine($"- {animal.rank}");
    };
    // I need to use new Program(), but you dont need to do that
    new Program().AsyncToConsole(uri, populateLabel );
    Console.ReadLine();
    return;
}
1
salomo hutapea On

You must first deserialize the JSON to a class, for example Organism class. Copy first our JSON file example. And then, we can use Edit --> Paste Special --> Paste JSON as classes.

So The class will be like this.

public class Organism
{
    public int usageKey { get; set; }
    public string scientificName { get; set; }
    public string canonicalName { get; set; }
    public string rank { get; set; }
    public string status { get; set; }
    public int confidence { get; set; }
    public string matchType { get; set; }
    public string kingdom { get; set; }
    public string phylum { get; set; }
    public string order { get; set; }
    public string family { get; set; }
    public string genus { get; set; }
    public string species { get; set; }
    public int kingdomKey { get; set; }
    public int phylumKey { get; set; }
    public int classKey { get; set; }
    public int orderKey { get; set; }
    public int familyKey { get; set; }
    public int genusKey { get; set; }
    public int speciesKey { get; set; }
    public bool synonym { get; set; }
    public string _class { get; set; }
}

After that, we can now access the class properties to that object as usual.

    public static List<string> GetOrganismList(string link)
    {
        List<string> returnList = new List<string>();
        var client = new RestClient(link);
        var request = new RestRequest(Method.GET);
        IRestResponse response = client.Execute(request);
        var listOrganism = JsonConvert.DeserializeObject<Organism>(response.Content);

        returnList.Add(" Kingdom: " + listOrganism.kingdom.ToString());
        returnList.Add(" Phylum: " + listOrganism.phylum.ToString());
        returnList.Add(" Order: " + listOrganism.order.ToString());
        returnList.Add(" Family: " + listOrganism.family.ToString());
        returnList.Add(" Genus: " + listOrganism.genus.ToString());
        returnList.Add(" Species: " + listOrganism.species.ToString());

        return returnList;
    }