4

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?

Hairy Mike
  • 43
  • 4
  • 3
    Serialization isn't the issue here. If you write the following code `var s1=new Stack(new[]{0,1,2,3,4});var s2=new Stack(s1);`, you'll see the same issue, and it stems from how the `Stack` constructor is written when supplied with an `IEnumerable` parameter. Fix? Deserialize to a list and reverse before constructing a stack? – spender Sep 13 '16 at 13:03
  • 2
    The default Enumerator of `Stack` enumerates the items in the order they would be popped off the stack. If you Push the items onto another stack in that order, the other stack will contain the items in reversed order. – Dennis_E Sep 13 '16 at 13:03

1 Answers1

1

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);
}
Nico
  • 3,542
  • 24
  • 29
  • Apologies for the duplicate question - I did search for this issue before posting. Thanks for the help everyone :) – Hairy Mike Sep 14 '16 at 09:30