I am using System.Text.Json and right now, I'm trying to figure out how to sort a JsonArray without deserializing it, if that is at all possible. I have been able go get other LINQ functions to work with JsonArrays, however, I cannot seem to get OrderBy to work and I am getting compile errors with everything I have tried.
When I set a var to be the result of the sorted array, VS says that it is:
IOrderedEnumerable<JsonNode>
VS will not allow me to convert this type to a JsonArray. If I use JsonArray instead of var, then I get the red squiggly lines and the error says:
CS0029: Cannot implicitly convert type 'System.Linq.IOrderedEnumerable<System.Text.Json.Nodes.JsonNode>' to System.Text.Json.Nodes.JsonArray
I have been looking all around and I have not had much luck when it comes to sorting JsonArrays. Is this even possible?
Below are some of the things I have tried:
private void SortArrayTest(JsonArray arrayToSort)
{
var sortedArray0 = arrayToSort.OrderBy(x => x["Name"].ToString());
JsonArray sortedArray1 = arrayToSort.OrderBy(x => x["Name"]);
JsonArray sortedArray2 = arrayToSort.OrderBy(x => x["Name"].ToString());
JsonArray sortedArray3 = arrayToSort.OrderBy(x => x["Name"].ToString()).ToArray();
JsonArray sortedArray4 = arrayToSort.OrderBy(x => x["Name"].ToString()).ToList();
JsonArray sortedArray5 = arrayToSort.OrderBy(x => x["Name"].ToString()).ToList<string>();
JsonArray sortedArray6 = arrayToSort.OrderBy(x => (string)x["Name"]).ToArray();
}
CodePudding user response:
try this
private JsonArray SortArrayTest(JsonArray arrayToSort)
{
return (JsonArray) Nodes.JsonArray.Parse(JsonSerializer
.Serialize(arrayToSort.OrderBy(x => (string) x["Name"])));
}
IMHO, it is better to use Newtonsoft.Json. In this case your code would be much more simple and readable
private JArray SortArrayTest(JArray arrayToSort)
{
return JArray.FromObject(arrayToSort.OrderBy(x => (string)x["Name"]));
}
CodePudding user response:
Enumerable.OrderBy()
does not sort the incoming sequence in-place. Instead it returns a new IEnumerable<T>
that, when iterated, returns the items of the original sequence in the required order. Thus to modify the contents of your JsonArray
you will have to clear it and re-add the ordered items, like so:
private static void SortArrayTest(JsonArray arrayToSort)
{
var sortedList = arrayToSort.OrderBy(x => x["Name"].ToString()).ToList();
arrayToSort.Clear();
foreach (var item in sortedList)
arrayToSort.Add(item);
}
Or, if you would prefer to create a new array and leave the original unchanged, you may serialize the ordered enumerable via JsonSerializer.SerializeToNode()
like so:
private static JsonArray SortNewArrayTest(JsonArray arrayToSort) =>
JsonSerializer.SerializeToNode(arrayToSort.OrderBy(x => x["Name"].ToString())).AsArray();
Notes:
A
JsonNode
knows its parent container (JsonArray
orJsonObject
) via itsParent
property. Thus it's not possible for a givenJsonNode
to belong to two parents at once.This explains why it is necessary to serialize the ordered enumerable to a new sequence of nodes, rather than simply materializing the ordered enumerable as an array and creating a new
JsonArray
from it that contains the existing nodes.JsonSerializer.SerializeToNode()
(new in .NET 6) is the equivalent of Newtonsoft'sJToken.FromObject()
.
Demo fiddle here.
CodePudding user response:
Some of you have provided some very helpful comments on how to sort a JsonArray directly, and after trying the recommendations, while they do work, it seems that it is much faster in terms of processing time to deserialize the JsonArray to a C# list, then sort, then re-serialize back to Json.