4

I'm working with a 3rd party REST API in which one of the fields (type string) has a known set of values that I've modeled as an enum in my code. The StringEnumConverter from JSON.NET correctly serializes all but one of these values as described by the [EnumMemberAttribute] annotation. For this field in particular, the REST API translates a null value to mean "System Default" in the 3rd party system; however, when JSON.NET serializes this it uses the member name instead of the value described in the annotation. I know I could write a custom converter to handle this , but my question is if there is a way to get this to work without one since it's only the null value that doesn't serialize correctly?

The enum I have defined in my code:

[JsonConverter(typeof(StringEnumConverter))]
public enum InitialScanLevel
{
    [EnumMember(Value = null)]
    SystemDefault,

    [EnumMember(Value = "0")]
    ModelDeviceOnly,

    [EnumMember(Value = "1")]
    InitialAppPopulation,

    [EnumMember(Value = "2")]
    DiscoverSslCerts,

    [EnumMember(Value = "3")]
    DiscoverOpenPorts,

    [EnumMember(Value = "4")]
    AdvancedPortDiscovery,

    [EnumMember(Value = "5")]
    DeepDiscovery
}

For InitialScanLevel.SystemDefault the resulting JSON is (not what the 3rd party API expects)

{
    other fields...,
    "initialScanLevel":"SystemDefault",
    other fields...
}

but should be

{
    other fields...,
    "initialScanLevel":null,
    other fields...
}

For InitialScanLevel.DeepDiscovery the resulting JSON is (this is what the 3rd party API expects)

{
    other fields...,
    "initialScanLevel":"5",
    other fields...
}
Chris
  • 325
  • 1
  • 5
  • 12
  • @Jashaszun thanks for the edit. I didn't realize ` would highlight those correctly. – Chris Jul 30 '14 at 16:03
  • Any time! :) BTW, you should probably read through the [formatting help](http://stackoverflow.com/editing-help). There are probably lots of good-to-know tidbits of information there (certainly there's stuff in there that I might have been able to use but didn't know about for other posts of mine). – Jashaszun Jul 30 '14 at 16:05
  • The reason for this behavior is that the *WriteJson* method StringEnumConverter does `string enumName = e.ToString();`. Fortunately, you can derive your own Converter from StringEnumConverter and override the *WriteJson* (and perhaps *ReadJson*) method. You'll need to implement there the desired behaviour for EnumMember value (or respective JSON value) being null. –  Jul 30 '14 at 16:10
  • @elgonzo I thought that was probably the solution but was optimistic that there might be a way to accomplish this with the annotations instead...thanks. – Chris Jul 30 '14 at 16:13
  • Unfortunately, in the source code for default StringEnumConverter when it parses the EnumMemberAttribute it will override null Value with the name of the enum value. – Michael Yoon Jul 30 '14 at 16:35
  • You can use JsonNetResult from this question http://stackoverflow.com/questions/23348262/using-json-net-to-return-actionresult/23349116#23349116 – Tomas Kubes Feb 18 '15 at 18:19
  • Does this answer your question? [How can I ignore unknown enum values during json deserialization?](https://stackoverflow.com/questions/22752075/how-can-i-ignore-unknown-enum-values-during-json-deserialization) – mfabruno Feb 11 '21 at 23:00

1 Answers1

8

I think the easies way to do it is using a custom StringEnumConverter

public class MyStringEnumConverter : Newtonsoft.Json.Converters.StringEnumConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value.Equals(InitialScanLevel.SystemDefault)) value = null;
        base.WriteJson(writer, value, serializer);
    }
}

[JsonConverter(typeof(MyStringEnumConverter))]
public enum InitialScanLevel
{
 .....
}
L.B
  • 114,136
  • 19
  • 178
  • 224
  • thanks @L.B, I thought that was probably the case. I implemented your solution with a slight variation to accomodate the other enums that have the same oddity as well as to call `StringEnumConverter.WriteJson()` instead of `base.WriteJson()` – Chris Jul 30 '14 at 17:15