21

I'm attempting to use Json.NET with the System.Net.Http.HttpClient to send an object with an enum property, however the enum is always serialized as an integer value rather than the string equivalent.

I've tried following the instructions here:

http://james.newtonking.com/archive/2013/05/08/json-net-5-0-release-5-defaultsettings-and-extension-data

By both adding an instance of StringEnumConverter to the JsonSerializerSettings and also tried to decorate the enum property with [JsonProperty(ItemConverterType = typeof(StringEnumConverter))] neither of which appear to be working in my example.

I'm using Json.NET version 5.0.8

Can anyone tell me what I'm doing wrong please? Here is a sample console app to replicate showing both the global serializer settings and the decorated property:

Thanks.

using System; using System.Net.Http; using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { HttpClient client = new HttpClient { BaseAddress = new Uri("http://test-uri.com") }; JsonConvert.DefaultSettings = (() => { var settings = new JsonSerializerSettings(); settings.Converters.Add(new StringEnumConverter()); return settings; }); var data = new TestData { Enum = TestEnum.Hello }; // The following posts: {"Enum":0} // Shouldn't it post {"Enum":"Hello"} instead? var result = client.PostAsJsonAsync("/test", data).Result; } public class TestData { [JsonProperty(ItemConverterType = typeof(StringEnumConverter))] public TestEnum Enum { get; set; } } public enum TestEnum { Hello, World } } } 

I've inspected this with Fiddler and it posts: {"Enum":0} rather than {"Enum":"Hello"} which is what I would expect.

4
  • Could it be, that you are not using the JsonConverter at all in your example? The serialization is made by the client object - HttpClient. I tried serializing the data object using JsonConvert.SerializeObject(data) and the output was correct: {"Enum":"Hello"}. So i think the HttpClient does not convert the enum to string. Commented Nov 1, 2013 at 16:52
  • You could well be right. I was under the impression that the HttpClient used Json.NET under the hood now. Perhaps I was wrong. I'll have a tinker and see what I can find. Commented Nov 1, 2013 at 16:59
  • It appears that it is using Json.NET under the hood - see Jeff's answer below. Commented Nov 1, 2013 at 17:03
  • Well, i didn't knew that. Commented Nov 1, 2013 at 17:07

2 Answers 2

26

The ItemConverterType property of the JsonPropertyAttribute attribute is the converter to use for items of a collection. You should be using the JsonConverterAttribute attribute.

public class TestData { [JsonConverter(typeof(StringEnumConverter))] public TestEnum Enum { get; set; } } 
Sign up to request clarification or add additional context in comments.

4 Comments

That works thanks! Do you have any ideas why the DefaultSettings aren't working too? As I'd prefer not to have to decorate my classes with serialization attributes if possible, but if I have to I will. Thanks again.
It should work as you have it right there, assuming that Json.net is actually doing the serializing, not the default serializer used in the PostAsJsonAsync() method. If it's not possible to override which serializer to use, it might be easier to serialize using Json.net, then post the resulting string.
@JeffMercado In your answer, should the order of "TestEnum" and "Enum" be inversed ?
@Alex: No, TestEnum is the name of the type of the property. Enum is the name of the property. If they were reversed (?), then they would have a very different meaning.
9

I think I've found a way of getting it to work without decorating attributes. It involves replacing client.PostAsJsonAsync() with client.PostAsync(). You can then specify the MediaTypeFormatter to use which in this case will be the JsonMediaTypeFormatter.

Source here: .net HttpClient with custom JsonConverter

 var settings = new JsonSerializerSettings(); settings.Converters.Add(new StringEnumConverter()); var formatter = new JsonMediaTypeFormatter { SerializerSettings = settings }; var response = client.PostAsync("/test", data, formatter).Result; 

This still doesn't explain why the DefaultSettings aren't being applied. I can only assume that the presence of the [JsonConverter] property forces the HttpClient to use Json.NET for serialization, otherwise it just uses the default serializer.

2 Comments

DefaultSettings are not applied because PostAsJsonAsync calls new JsonMediaTypeFormatter() which creates new instance of JsonSerializerSettings and bypasses default settings. It is wrong and annoying.
Is this by design or a bug?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.