How best to turn a JArray of type Type into an array of Types?
C#json.netC# Problem Overview
I've got a JArray
that represents the json substring [1,2,3]
. I'd like to turn it into an int[]
instead.
What's the correct way of doing this? The best way I've found so far is to do the following:
int[] items = new int[myJArray.Count];
int i = 0;
foreach (int item in myJArray)
{
items[i++] = item;
}
C# Solutions
Solution 1 - C#
myJArray.ToObject<int[]>();
You can also specify HashSet, List etc.
The accepted answer relies on .NET's conversion - this technique uses JSON.NET's own in addition to what .NET can provide so works with more scenarios.
It's also faster as it isn't using a generator & closure for the LINQ operation.
Solution 2 - C#
int[] items = myJArray.Select(jv => (int)jv).ToArray();
Solution 3 - C#
A cast needed first for me:
((Newtonsoft.Json.Linq.JArray)myJArray).Select(item => (int)item).ToArray()
Solution 4 - C#
This is pretty weak because you have to convert back into a string, but if you are doing something quick and dirty, where the performance hit won't matter, I use the below method. I like it because I don't have to write any code to map properties between json/JObject and my POCO's.
public static class JsonExtensions {
public static T As<T>(this JObject jobj) {
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(jobj));
}
public static List<T> ToList<T>(this JArray jarray) {
return JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(jarray));
}
}
[Test]
public void TestDeserializeRootObject() {
var json = @"{ id: 1, name: ""Dwight"" }";
var jfoo = JsonConvert.DeserializeObject(json);
var foo = (jfoo as JObject).As<Foo>();
Assert.AreEqual(1, foo.Id);
Assert.AreEqual("Dwight", foo.Name);
}
[Test]
public void TestDeserializeArray() {
var json = @"[
{ id: 1, name: ""Dwight"" }
, { id: 2, name: ""Pam"" }
]";
var foosArr = JsonConvert.DeserializeObject(json);
Assert.IsInstanceOf<JArray>(foosArr);
Assert.AreEqual(2, (foosArr as JArray).Count);
var foos = (foosArr as JArray).ToList<Foo>();
Assert.AreEqual(2, foos.Count);
var foosDict = foos.ToDictionary(f => f.Name, f => f);
Assert.IsTrue(foosDict.ContainsKey("Dwight"));
var dwight = foosDict["Dwight"];
Assert.AreEqual(1, dwight.Id);
Assert.AreEqual("Dwight", dwight.Name);
Assert.IsTrue(foosDict.ContainsKey("Pam"));
var pam = foosDict["Pam"];
Assert.AreEqual(2, pam.Id);
Assert.AreEqual("Pam", pam.Name);
}
Solution 5 - C#
int[] items = new int[myJArray.Count];
for (int i=0; i < myJArray.Count;i++)
{
items[i] = (int)myJArray[i]
}
this is the fastes solution you can do. The classic for
is a bit faster than the ForEach
as you access the item by the index(the foreach behind the scene uses the IEnumerator interface)
or if you prefer:
JsonArray arr = JsonConvert.Import("[1,2,3,4]");
int[] nums = (int[]) arr.ToArray(typeof(int));