Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selectively use default JSON converter

I use the following in my Web API project's Startup.cs to JSON-serialize Enums into strings:

// Configure JSON Serialization
var jsonSerializationSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
jsonSerializationSettings.Formatting = Newtonsoft.Json.Formatting.None;
jsonSerializationSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());

This is to avoid decorating every Enum property with [JsonConverter(typeof(StringEnumConverter))]

Now, how can I selectively opt out of my global serialization setting for some Enum properties and use the default serializer that converts to integers?

like image 355
orad Avatar asked Sep 28 '16 05:09

orad


People also ask

What is JsonSerializerSettings?

Specifies the settings on a JsonSerializer object. Newtonsoft.Json. JsonSerializerSettings. Namespace: Newtonsoft.Json.

What is Jsonconvert SerializeObject C#?

SerializeObject Method (Object, Type, JsonSerializerSettings) Serializes the specified object to a JSON string using a type, formatting and JsonSerializerSettings. Namespace: Newtonsoft.Json.


1 Answers

You could add a dummy converter to the properties in question that does nothing:

public class NoConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        // Note - not called when attached directly via [JsonConverter(typeof(NoConverter))]
        throw new NotImplementedException();
    }

    public override bool CanRead { get { return false; } }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Then attach it to the property using [JsonConverter(typeof(NoConverter))]. Having done so, the JsonConverter attribute's converter supersedes the globally specified converter, but since CanRead and CanWrite both return false no conversion is performed. For collections of enums, you could use [JsonProperty(ItemConverterType = typeof(NoConverter))].

For instance, if you define the types:

public enum Foo { A, B, C }

public class RootObject
{
    [JsonConverter(typeof(NoConverter))]
    public Foo FooAsInteger { get; set; }

    public Foo FooAsString { get; set; }
}

Then

var root = new RootObject { FooAsInteger = Foo.B, FooAsString = Foo.B };

var json = JsonConvert.SerializeObject(root, Formatting.Indented, new StringEnumConverter());

Console.WriteLine(json);

Produces the output

{
  "FooAsInteger": 1,
  "FooAsString": "B"
}

Note that you can also apply NoConverter directly to the enum, if you want all occurrences of the enum in all data models to be serialized as an integer:

[JsonConverter(typeof(NoConverter))]
public enum FooAlwaysAsInteger { A, B, C }

Sample fiddle.

like image 74
dbc Avatar answered Nov 07 '22 20:11

dbc