While playing around Stack collection in C# I encountered the following issue. Exactly I am not sure why it is happening. Please put some light on the reason and alternative to the solution.
Problem -
A class having Stack as property. For example name that class as Progress. T is of class type Item.
Now whenever the user makes any progress we will be storing in stack. And if user leaves in between, then next time we will peek the item from the stack so from that stage. Below code snippet will give an idea of what is being tried...
using static System.Console;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace StackCollection
{
class Program
{
static void Main(string[] args)
{
Progress progress = new Progress();
progress.Items.Push(new Item { PlanID = null, PlanName = "Plan A" });
var jsonString = JsonConvert.SerializeObject(progress);
var temp = JsonConvert.DeserializeObject<Progress>(jsonString);
temp.Items.Push(new Item { PlanID = null, PlanName = "Plan B" });
jsonString = JsonConvert.SerializeObject(temp);
temp = JsonConvert.DeserializeObject<Progress>(jsonString);
temp.Items.Push(new Item { PlanID = null, PlanName = "Plan C" });
jsonString = JsonConvert.SerializeObject(temp);
temp = JsonConvert.DeserializeObject<Progress>(jsonString);
WriteLine(temp.Items.Peek().PlanName);
ReadLine();
}
}
class Progress
{
public Stack<Item> Items { get; set; }
public Progress()
{
Items = new Stack<Item>();
}
}
class Item
{
public string PlanID { get; set; }
public string PlanName { get; set; }
}
}
now the line -
WriteLine(temp.Items.Peek().PlanName);
should return
Plan C
but it is returning
Plan B
So, why the index is being changed, any clue or pointer will be helpful.
It seems like the stack is being serialized as a List. The problem is that this does not preserve the proper order when deconstructing the stack (the items are actually pushed in the reverse order). Here's a quick workaround to this issue:
Since this is a known behavior of Json.NET, as noted by this answer, a custom
JsonConverter
can be used when deserializing a stack that pushes items on in the correct order.The following universal converter can be used with
Stack<T>
for anyT
:Then add it to
JsonSerializerSettings
to correct the ordering of stacks when deserializing:Or mark the
Stack<T>
property directly with[JsonConverter(typeof(StackConverter))]
:If you try to debug it then you will notice that items order is broken after
Stack
deserialization.The same question has been asked on JSON.NET GitHub issue tracker a month ago.
The answer from JamesNK: