Hairy Mike Hairy Mike - 2 months ago 6
C# Question

Order of stack elements is reversed after serialising and de-serialising with Newtonsoft.Json

I'm having a problem with the order of elements in a stack being reversed when serialised / de-serialised. See this demo for repro:

using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace StackChecker
{
class Program
{
enum Screen
{
Unknown,
Bypass,
ClaimDetails,
ClaimSearch,
ClaimSearchResults,
PatientSearchResults
}

static void Main(string[] args)
{
var screens = new Stack<Screen>();
screens.Push(Screen.Unknown);
screens.Push(Screen.Bypass);
screens.Push(Screen.ClaimDetails);
screens.Push(Screen.ClaimSearch);
screens.Push(Screen.ClaimSearchResults);
screens.Push(Screen.PatientSearchResults);

foreach (var screen in screens)
{
Console.WriteLine("Screen {0}: {1}", (int)screen, screen);
}

var screenJson = JsonConvert.SerializeObject(screens);
Console.WriteLine("Screens Json: \"{0}\"", screenJson);

var screens2 = JsonConvert.DeserializeObject<Stack<Screen>>(screenJson);
foreach (var screen in screens2)
{
Console.WriteLine("Screen {0}: {1}", (int)screen, screen);
}

var screenJson2 = JsonConvert.SerializeObject(screens2);
Console.WriteLine("Screens Json: \"{0}\"", screenJson2);

Console.ReadLine();
}
}
}


This outputs the following:

Screen 5: PatientSearchResults
Screen 4: ClaimSearchResults
Screen 3: ClaimSearch
Screen 2: ClaimDetails
Screen 1: Bypass
Screen 0: Unknown
Screens Json: "[5,4,3,2,1,0]"
Screen 0: Unknown
Screen 1: Bypass
Screen 2: ClaimDetails
Screen 3: ClaimSearch
Screen 4: ClaimSearchResults
Screen 5: PatientSearchResults
Screens Json: "[0,1,2,3,4,5]"


So, question is - Why is the order reversed? (I have also tried this with an array and can prove that array elements are not reversed)

Can this be avoided?

If not, anyone got an idea for an elegant workaround?

Answer

You could deserialize to a List like var screens2 = JsonConvert.DeserializeObject<List<Screen>>(screenJson). If you need a stack as datastructure, then you can create a temporary list which you reverse and copy to the stack.

var screensTemp = JsonConvert.DeserializeObject<List<Screen>>(screenJson);
screensTemp.Reverse();
var screens2 = new Stack<Screen>(screensTemp);
foreach (var screen in screens2)
{
    Console.WriteLine("Screen {0}: {1}", (int)screen, screen);
}