0

Sorry for basic question, I'm beginner and tried to find my problem, but wasn't able to

string json = "{\"EmailList\":[{\"name\":\"John Bravo\",\"email\":\"email@gmail.com\"},{\"name\":\"Daniel Alutcher\",\"email\":\"email@gmail.com\"},{\"name\":\"James Rodriguez\",\"email\":\"email@gmail.com\"}]}";

JObject rss = JObject.Parse(json);

var data = JsonConvert.DeserializeObject<dynamic>(json);

dynamic emails = data.EmailList;

List<string> emailList = new List<string>();

foreach (dynamic item in emails)
{
    int x = 0;
    if (item.email != null)
    {
        Console.WriteLine(item.email);
        //emailList.Add(item.email); // throws exception System.Collections.Generic.List<string>.Add(string)' has some invalid arguments' 
    }
}

So I'm looping trough this JSON and I'm able to get in console each email, but when I'm trying to add it to a list, it's throwing exception error

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
onlyo
  • 53
  • 5
  • list.Add(item.email as string); Have fun :) – Leron Oct 22 '20 at 13:55
  • @Leron_says_get_back_Monica While that will get rid of the exception, the list will be full of `null`s, since the dynamic objects aren't strings as such. – Lasse V. Karlsen Oct 22 '20 at 14:06
  • You can simplify this whole question down to this code: `dynamic test = new JValue("Test"); new List().Add(test);`, and I wonder why that fails, since `string s = test;` works just fine. – Lasse V. Karlsen Oct 22 '20 at 14:08

2 Answers2

1

As you commented "IS there any way to avoid "dynamic" in this code?".

Well there is and it's pretty simple, It's a simple copy past!
In Visual Studio using the special past in top bar menu (image).
Or in an online tool like app.quicktype.io or json2csharp.com.

using  Newtonsoft.Json;

public partial class JsonData //Give it a better name
{
       [JsonProperty("EmailList")] public List<EmailInformation> EmailList { get; set; }
}

public partial class EmailInformation
{
       [JsonProperty("name")]  public string Name { get; set; } 
       [JsonProperty("email")] public string Email { get; set; }
}

And the usage is pretty straightforward too, and you already have most of it in your code:

var data = JsonConvert.DeserializeObject<JsonData>(json);

foreach(var mailInfo  in data.EmailList){
       Console.WriteLine($"{mailInfo.Name} <{mailInfo.Email}>;");
}

//here a list of string 
var emails = data.EmailList.Select(x=> x.Email).ToList();
Drag and Drop
  • 2,672
  • 3
  • 25
  • 37
  • Thank you! This is exactly what I needed :) – onlyo Oct 22 '20 at 15:16
  • and what if this JSON would be in Appsettings as a part of whole appsettings json? How would be it possible to import it to Program.cs ? – onlyo Oct 22 '20 at 15:51
  • @onlyo, you are on Core? [How to read AppSettings values from a .json file](https://stackoverflow.com/questions/31453495/how-to-read-appsettings-values-from-a-json-file-in-asp-net-core). Then The documentation will be the thing to check https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1. Hierachical and Bind an array will be a must read. – Drag and Drop Oct 22 '20 at 16:00
0

You're Trying to add dynamic in List<string> instead you should do

emailList.Add(item.email.ToString()); 

Code:

string json =
"{\"EmailList\":[{\"name\":\"John Bravo\",\"email\":\"email@gmail.com\"},{\"name\":\"Daniel Alutcher\",\"email\":\"email@gmail.com\"},{\"name\":\"James Rodriguez\",\"email\":\"email@gmail.com\"}]}";


JObject rss = JObject.Parse(json);

var data = JsonConvert.DeserializeObject<dynamic>(json);

dynamic emails = data.EmailList;

List<string> emailList = new List<string>();

foreach (dynamic item in emails)
{
    int x = 0;
    if (item.email != null)
    {
        Console.WriteLine(item.email);
        emailList.Add(item.email.ToString()); // Change here 
   }
}
Mihir Dave
  • 3,954
  • 1
  • 12
  • 28
  • I am wondering why `.Add((string)item.email)` works just fine, but `.Add(item.email)` doesn't. – Lasse V. Karlsen Oct 22 '20 at 14:05
  • @LasseV.Karlsen IMO item.email in the current state has type dynamic which is not string what Add requires. so we explicitly need to cast that. – Mihir Dave Oct 22 '20 at 14:09
  • Adding `dynamic` to a `List` should really work just fine, assuming the value in the dynamic is coercible to a string. For instance, you can do this, and it works: `string s = item.email;` The underlying object is of type `JValue`, but again, it works when assigning directly to a string variable, so I wonder why it doesn't allow this when calling a method that only accepts a string parameter. – Lasse V. Karlsen Oct 22 '20 at 14:09
  • I asked a new question instead - https://stackoverflow.com/questions/64484213/why-is-a-jvalue-held-in-a-dynamic-variable-assignable-to-a-string-variable-b – Lasse V. Karlsen Oct 22 '20 at 14:18
  • @LasseV.Karlsen string s = item.email works because of implicit conversions https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic#conversions whereas when calling add method because it's a value type it breaks try the adding reference type and it'll work like a charm – Mihir Dave Oct 22 '20 at 14:19
  • Wow Lasse, you're inspiring! – onlyo Oct 22 '20 at 14:19
  • @MihirDave I'm sorry but I still don't buy that. There's no implicit conversion from `JValue` to a `string`, nor is `JValue` a value type, it's a class. – Lasse V. Karlsen Oct 22 '20 at 14:22
  • 1
    @LasseV.Karlsen I didn't see your edited comment about JValue, now I'm as much curious as you're, following your asked question. thanks for asking this. – Mihir Dave Oct 22 '20 at 14:24
  • @onlyo, yes Dynamic only for "Ok this class definition is to hard you will do it and execution". So the solution is a to create a class that represent the Json data. And it's easy. It's a simple copy past! In visual studio using the special past in top bar. Or in an online tool like [https://app.quicktype.io/](https://app.quicktype.io?share=7pfDSgABGd68X32BYRcG) or https://json2csharp.com/. Then the whole code boils down to `var data = JsonConvert.DeserializeObject(json);` And this will have your list in `data.EmailList` – Drag and Drop Oct 22 '20 at 14:38
  • @DragandDrop, thank you! I think I will do it instead of risking by throwing exceptions – onlyo Oct 22 '20 at 14:52
  • @onlyo, rule of thumb for Dynamic is: "You don't need it. If you do, you are doing some Silverlight. Or COM interop." – Drag and Drop Oct 22 '20 at 15:02