3

I am trying to serialize an anonymous class as follows:

public enum ErrorCode 
{
    A,
    B,
    C
}

var response = JObject.FromObject(new
{
    Error = new
    {
        Message = "Test",
        Code = ErrorCode.A
    }
})
.ToString(Formatting.None, new StringEnumConverter());

I expect response to be:

{"Error":{"Message":"Test","Code":"A"}}

but I get:

{"Error":{"Message":"Test","Code":0}}

I do get the correct response if I add [JsonConverter(typeof(StringEnumConverter) attribute to the enum but I can't do that due to unrelated reasons.

You can find sample code here.

Am I missing something obvious here? My approach is similar to the example here

Sanjid
  • 133
  • 1
  • 6
  • https://stackoverflow.com/a/2870420/10496806 Try to create non-anonymous class and mark enum property with [JsonConverter(typeof(StringEnumConverter))] attribute – Woldemar89 Jan 24 '19 at 07:19

1 Answers1

4

Your problem is that you are applying StringEnumConverter too late in the process. Json.NET converts the enum to a string or integer when your POCO is serialized to a JObject hierarchy, but you are supplying the converter later, when the JObject is finally formatted as a string.

Instead, supply the converter when serializing to JObject by using JObject.FromObject(Object, JsonSerializer) and constructing a serializer with the desired settings:

var response = JObject.FromObject(
    new
    {
        Error = new
        {
            Message = "Test",
            Code = ErrorCode.A
        }
    },
    JsonSerializer.CreateDefault(new JsonSerializerSettings { Converters = { new StringEnumConverter() } })
)
.ToString(Formatting.None);

Sample fiddle here.

(You might reasonably ask, when do the converters supplied to JToken.ToString(Formatting,JsonConverter[]) ever matter? While, in general, converters are applied during serialization to JToken, these converters are useful to control formatting of value types that Newtonsoft stores directly inside JValue.Value without modification. Most notably, DateTime values are stored directly in the JToken hierarchy without conversion during serialization. This, in turn, happens because Newtonsoft recognizes DateTime values during tokenizing of a JSON stream by JsonTextReader, necessitating the ability to store the resulting DateTime objects inside a JValue. For details see here and here. Conversely, as Json.NET does not try to recognize enum values during parsing, there was never a need to retain them in a JToken hierarchy. Thus they're converted to strings or integers during the serialization phase.)

dbc
  • 104,963
  • 20
  • 228
  • 340