0

Why don't we see the enum keys in the serialized response? It only works with the keys in a dictionary.

TestMethod]
public void TestMethod5()
{
    string response = "{\"risk\":\"LOW\",\"topics\":{\"CAT\":\"LOW\",\"LION\":\"HIGH\"}}";
    Resource deserializedResource = JsonConvert.DeserializeObject<Resource>(response);
    string serializedResource = JsonConvert.SerializeObject(deserializedResource);

    Console.WriteLine(serializedResource); 
    // actual        = {"risk":10,"topics":{"CAT":10,"LION":30}}
    // expectation_1 = {"risk":LOW,"topics":{"CAT":LOW,"LION":HIGH}} OR
    // expectation_2 = {"risk":10,"topics":{"0":10,"2":30}}
}
// sample resource and enums
public class Resource
{
    [JsonProperty("risk")]
    public Risk RiskFactor { get; set; }
    [JsonProperty("topics")]
    public IDictionary<Animal, Risk> Animals { get; set; }
}
public enum Risk
{
    LOW = 10,
    MEDIUM = 20,
    HIGH = 30
}
public enum Animal
{
    CAT = 0,
    BULL = 1,
    LION = 2
}
Devendra Lattu
  • 2,732
  • 2
  • 18
  • 27
  • 1
    Check this https://stackoverflow.com/a/18551699/5446495 – Genusatplay Mar 25 '21 at 05:32
  • `Microsoft.AspNetCore.Mvc.NewtonsoftJson` v3.1.7 – Devendra Lattu Mar 25 '21 at 05:32
  • 2
    Attach `[JsonConverter(typeof(StringEnumConverter))]` on `Risk` enum to get the desired output. – user1672994 Mar 25 '21 at 05:34
  • 1
    JSON.NET always treats dictionary keys as strings, which is why you're seeing a string value for the dictionary key. – ProgrammingLlama Mar 25 '21 at 05:34
  • @llama but I suppose the question is then why pick the name rather than the number? It could just as easily be "0":10 rather than "CAT":10, no? – Caius Jard Mar 25 '21 at 06:20
  • @Caius I suppose so, but I would assume that it favours actual string values, so it presumably calls `.ToString()` on the enum value. Interestingly, that doesn't seem to be the general behaviour because using a `List` as a key yields "(Collection)" rather than "System.Collections.Generic.List`1[System.String]" – ProgrammingLlama Mar 25 '21 at 06:31
  • 1
    Interesting (though I suppose my question is off topic as questions of the form "what was Jane's Newton kind thinking when.." are realistically only answerable by JNK.. ) - given that one of JSON's missions is brevity, compared to soap, I did wonder if using a string form of whichever is shorter chars out of the enum name vs the number is a help or a hindrance; I suppose it depends on the receiving end's ability to unpack either form to something useful. Perhaps consistency was deemed more important. Maybe string was picked because it is unambiguous whereas enum members can be the same int – Caius Jard Mar 25 '21 at 06:42
  • 1
    (Though c# wouldn't care either way; an enum it Cat=0,Dog=0 desert and becomes Cat/Dog if Dog/Cat is sent perhaps the receiving system cares more, or if it's a bug, then using the form that is compile mandated unique in c# gives an opportunity for better clarity somewhere..) – Caius Jard Mar 25 '21 at 06:45

1 Answers1

4

Attach [JsonConverter(typeof(StringEnumConverter))] on Risk enum to get the desired output

Code:

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
                    
public class Program
{
    public static void Main()
    {
        string response = "{\"risk\":\"LOW\",\"topics\":{\"CAT\":\"LOW\",\"LION\":\"HIGH\"}}";
        Resource deserializedResource = JsonConvert.DeserializeObject<Resource>(response);
        string serializedResource = JsonConvert.SerializeObject(deserializedResource);

        Console.WriteLine(serializedResource); 
    }
}

public class Resource
{
    [JsonProperty("risk")]
    public Risk RiskFactor { get; set; }
    [JsonProperty("topics")]
    public IDictionary<Animal, Risk> Animals { get; set; }
}

[JsonConverter(typeof(StringEnumConverter))]  
public enum Risk
{
    LOW = 10,
    MEDIUM = 20,
    HIGH = 30
}
public enum Animal
{
    CAT = 0,
    BULL = 1,
    LION = 2
}

The above returns the expected output

{"risk":"LOW","topics":{"CAT":"LOW","LION":"HIGH"}}

Check this dotnet fiddle - https://dotnetfiddle.net/wIxRf4

user1672994
  • 10,509
  • 1
  • 19
  • 32