1

JSON

{
  "count": 3,
  "value": [
    {
      "id": "AAAAAAAAAAAAA",
      "description": "test1",
      "name": "name1"
    },
    {
      "id": "BBBBBBBBBB",
      "description": "test2",
      "name": "name2"
    },
    {
      "id": "CCCCCCCCCCCC",
      "description": "test3",
      "name": "name3"
    }
  ]
}

I have a code in my solution retrieving from a LIST api and giving the JSON above. How can I use a LINQ to retrieve specific values? (e.g) I need to select name1 and I will get the id,description,name values.

I am using a dynamic variable in my code:

dynamic json = JObject.Parse(client.GetString().Result);

I'd been tinkering with other online guides the past few hours. However, can't get the result right.

Please help.

Hexxed
  • 683
  • 1
  • 10
  • 28
  • 1
    why are you using `dynamic` here ? Since you already know the structure of your JSON, then you should create a Type for it. – Pac0 Oct 03 '18 at 09:27
  • im using dynamic for shorter code lines and using core. But im still new to this. I'll only use the values once, CMIIW so I think its not good to make another object? – Hexxed Oct 03 '18 at 09:29
  • 2
    I've never seen **anyone** using `dynamic` *for shorter code lines* – Rafalon Oct 03 '18 at 09:30
  • @Hexxed : yes you should not use `dynamic` in this case, and create a proper type here. With a strongly typed language like C#, that's the way to go. The rationale behind adding `dynamic` in the language was to allow calls that could return non-determined structures / types, for instance calls to external DLL / COM things. You want to use it only if you are really stuck otherwise. – Pac0 Oct 03 '18 at 09:38
  • 1
    I do agree with @Pac0, there's no need to use dynamics here, given that you already know the structure of the json string. Don't use dynamics unless you have a very good reason to do it. Check [Advantages and Disadvantages of C# 4.0 'dynamic' keyword?](https://stackoverflow.com/questions/8203347/advantages-and-disadvantages-of-c-sharp-4-0-dynamic-keyword) – Rui Jarimba Oct 03 '18 at 09:43

4 Answers4

4

One solution would be to deserialize your JSON string into C# objects and then use Linq to get a specific object.

C# class definitions:

public class Content
{
    [JsonProperty("count")]
    public int Count { get; set; }

    [JsonProperty("value")]
    public List<Value> Values { get; set; }

    public Content()
    {
        Values = new List<Value>();
    }
}

public class Value
{
    [JsonProperty("id")]
    public string Id { get; set; }

    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }
}

Deserializing and getting the object:

string json = @"{
""count"": 3,
""value"": [
  {
    ""id"": ""AAAAAAAAAAAAA"",
    ""description"": ""test1"",
    ""name"": ""name1""
  },
  {
    ""id"": ""BBBBBBBBBB"",
    ""description"": ""test2"",
    ""name"": ""name2""
  },
  {
    ""id"": ""CCCCCCCCCCCC"",
    ""description"": ""test3"",
    ""name"": ""name3""
  }
]
}";


Content content = JsonConvert.DeserializeObject<Content>(json);

Value value = content.Values.FirstOrDefault(x => x.Name.Equals("name1", StringComparison.InvariantCultureIgnoreCase));
Rui Jarimba
  • 11,166
  • 11
  • 56
  • 86
  • this will work like a charm, however I only using the JSON value once and dispose of it. is making C# objects more efficient than using other `dynamic` solutions? – Hexxed Oct 03 '18 at 09:35
  • @Hexxed I don't know which solution is the most performant, you'd need to run some benchmarks to check that. For such a simple json string I'd say it won't make much difference – Rui Jarimba Oct 03 '18 at 09:38
  • 2
    @Hexxed - *is making C# objects more efficient than using other dynamic solutions?* - https://stackify.com/top-11-json-performance-usage-tips/ suggests to *Use pre-defined typed classes* for faster performance. That being said, see also https://ericlippert.com/2012/12/17/performance-rant/ See also [How does having a dynamic variable affect performance?](https://stackoverflow.com/q/7478387) which indicates that using `dynamic` always has a performance penalty, which possibly might be small. – dbc Oct 03 '18 at 12:27
2

First, you can create a class to represent a client:

public class Client
{
    public string Id { get; set; }
    public string Description { get; set; }
    public string Name { get; set; }
}

With this class, you can use JObject.Parse (as you're already doing) to parse the JSON into something that can be queried, use SelectToken to pull out the value array and then use ToObject to convert that to a list of Clients. Here's what that looks like:

var jsonObject = JObject.Parse(json_source);
var jsonObjectValue = jsonObject.SelectToken("value");
var clients = jsonObjectValue.ToObject<List<Client>>();

Once you've got your clients variable, you can use a simple LINQ statement to find the one that is name1:

var clientWithName1 = clients.SingleOrDefault(x => x.Name == "name1");

In this case, clientWithName will be null if no such client was found.

Here's a dotnetfiddle that demonstrates a complete solution.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
  • 1
    I like this solution more. Just to add my two cents: jsonObject["value"] is a JArray already, so we can save a variable, and turns out to this: `var jsonObject = JObject.Parse(json_source); var clients = (jsonObject["value"]).ToObject>();` – WalterAgile Mar 18 '21 at 15:28
  • Thanks for the input, @WalterAgile. You could even go as far as this: `var clients = JObject.Parse(json_source)["value"].ToObject>();`. :) – Kirk Larkin Mar 18 '21 at 15:38
1

Create an object Client that has properties id, description and name. Deserialize the json into a list of these objects.

List<Client> clients = JsonConvert.Deserialize<List<Client>>(json_source);
string desc = clients[0].description;
Peter Marshall
  • 1,231
  • 1
  • 13
  • 22
  • 1
    And then `clients.First[OrDefault](c => c.name == "name1");` – Rafalon Oct 03 '18 at 09:23
  • 1
    @KirkLarkin that's right, it should be an object with a list of Clients as written in RuiJarimba's answer. Still, the idea to deserialize to a proper type instead of `dynamic` is what makes it easier to use Linq afterwards – Rafalon Oct 03 '18 at 09:41
  • 2
    This is not the right answer - you cannot assume that the object with `name1` will be always the first one in the array, you need to query the deserialized array, as already mentioned by @Rafalon – Rui Jarimba Oct 03 '18 at 09:49
-1

Apparently with fiddling with my code I found an answer for myself. Thanks for to the ones trying to help me for giving me ideas.

var requestWorkProcess = await client.GetStringAsync("my url");
var workProcessId = JObject.Parse(requestWorkProcess)["value"].Children<JObject>().FirstOrDefault(o => o["name"].ToString() == workProcess).GetValue("id");
Hexxed
  • 683
  • 1
  • 10
  • 28
  • 1
    Not a downvoter, but this answer would not be the recommended way. It seems you are using everything in your power to circumvent any type safety provided by the language. – Pac0 Oct 03 '18 at 15:26