I have a class, which has as a property a collection of instances of another class:
class Inventory
{
public List<InventoryItem> Items
{
get;
set;
}
}
InventoryItem has a few properties, including a DateTime Start, but I will omit its implementation for brevity.
The class above deserializes correctly out of the box, with Newtonsoft.Json:
string serialization = "{ 'Items': [ { 'Amount': 1, 'Start': '2018-01-14T00:00:00', 'Id': 0 } ] }";
var inventory = JsonConvert.DeserializeObject<Inventory>( serialization );
Assert.AreEqual( inventory.Items.First().Amount, 1 );
However, what I want is to sort Items, by Start, as follows:
class Inventory
{
private List<InventoryItem> _inventoryItems = new();
public List<InventoryItem> Items
{
// order them before returning
get => this._inventoryItems.OrderBy( t => t.Start ).ToList();
set => this._inventoryItems = value;
}
}
Now the deserialization fails. The Inventory class is created, but no inventory items are created. I can make this work with a custom converter, but it seems to me there ought to be an easier way.
CodePudding user response:
My best guess as to what's happening here is Json.NET is setting your property to a new instance of List<InventoryItem>
and using Add
to add each item to the list.
In your getter, you're ordering it then using .ToList()
to convert it back to a list. This creates a new instance of List<InventoryItem>()
, which means the items are getting added to a different list each time, all of which are being thrown away.
However, List<T>
does have a .Sort()
method you can utilize. Unfortunately though it returns void, so we can't make it a one-liner. In your case, the implementation of this would look a little like this:
class Inventory
{
private List<InventoryItem> _inventoryItems = new();
public List<InventoryItem> Items
{
// order them before returning
get
{
this._inventoryItems.Sort((x, y) => x.Start > y.Start ? 1 : -1);
return this._inventoryItems;
}
set => this._inventoryItems = value;
}
}
A little bit of an explanation on the Sort()
method; It will always sort ascending. Returning 1 means that x
is greater than y
, returning -1 means that y
is greater than x
, and returning 0 means they're equal. In this example, it's sorting by Start
ascending. To sort descending, you can either flip the sign or flip the values in the ternary statement.