I've got the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var json = JsonConvert.DeserializeObject<dynamic>("[\"test1\", \"test2\"]");
var list = json.ToObject<IEnumerable<string>>().Concat(new[] { "test3" });
Console.WriteLine(string.Join(", ", list));
}
}
I would expect the result to be "test1, test2, test3" but instead this throws an exception:
[Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.Collections.Generic.List' does not contain a definition for 'Concat'] at CallSite.Target(Closure , CallSite , Object , String[] ) at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1) at Program.Main() :line 10
As far as I can tell in testing, both sides of the Concat
should be a version of IEnumerable<string>
.
I've gotten a successful try doing this:
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var json = JsonConvert.DeserializeObject<dynamic>("[\"test1\", \"test2\"]");
var list = (json as IEnumerable<dynamic>).Select(item => (string)item).Concat(new[] { "test3" });
Console.WriteLine(string.Join(", ", list));
}
}
But that's a bit clunky.
What am I doing wrong? Am I missing something?
CodePudding user response:
Your code was super simple to fix. Here it is:
var json = JsonConvert.DeserializeObject<dynamic[]>("[\"test1\", \"test2\"]");
var list = json.Concat(new[] { "test3" });
Console.WriteLine(string.Join(", ", list));
You just needed to change dynamic
to dynamic[]
.
Remember that dynamic
is just compiler trickery for object
-that-doesn't-throw-compiler-errors. But it isn't something that is enumerable. However, dynamic[]
is.
But for that matter, object[]
, and even string[]
, works.
string[] json = JsonConvert.DeserializeObject<string[]>("[\"test1\", \"test2\"]");
IEnumerable<string> list = json.Concat(new[] { "test3" });
Console.WriteLine(string.Join(", ", list));
My advice is avoid dynamic
in almost all cases. Use strong-typing instead.
CodePudding user response:
Borrowing the solution from here, I tried assigning the output of ToObject() method to a new variable with explicit type like so:
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var json = JsonConvert.DeserializeObject<dynamic>("[\"test1\", \"test2\"]");
IEnumerable<string> jsonAsEnumerable = json.ToObject<IEnumerable<string>>();
var list = jsonAsEnumerable.Concat(new[] { "test3" });
Console.WriteLine(string.Join(", ", list));
}
}
It seems to do the trick.