Home > Software engineering >  System.Text.Json - How do I sort JsonArray using OrderBy?
System.Text.Json - How do I sort JsonArray using OrderBy?

Time:05-13

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 or JsonObject) via its Parent property. Thus it's not possible for a given JsonNode 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's JToken.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.

  • Related