【问题标题】:Json.NET StringEnumConverter not working as expectedJson.NET StringEnumConverter 未按预期工作
【发布时间】:2013-11-01 16:39:30
【问题描述】:

我正在尝试将 Json.NET 与 System.Net.Http.HttpClient 一起使用来发送具有枚举属性的对象,但是该枚举始终被序列化为整数值,而不是等效的字符串。

我已尝试按照此处的说明进行操作:

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

通过将 StringEnumConverter 的实例添加到 JsonSerializerSettings 并尝试使用 [JsonProperty(ItemConverterType = typeof(StringEnumConverter))] 装饰枚举属性,这在我的示例中似乎都不起作用。

我使用的是 Json.NET 5.0.8 版

谁能告诉我我做错了什么吗?这是一个示例控制台应用程序,用于复制显示全局序列化程序设置和修饰属性:

谢谢。

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
        }
    }
}

我已经用 Fiddler 进行了检查,它发布了:{"Enum":0} 而不是 {"Enum":"Hello"},这是我所期望的。

【问题讨论】:

  • 有没有可能,您的示例中根本没有使用 JsonConverter?序列化由客户端对象 - HttpClient 进行。我尝试使用 JsonConvert.SerializeObject(data) 序列化数据对象,输出正确:{"Enum":"Hello"}。所以我认为 HttpClient 不会将枚举转换为字符串。
  • 你很可能是对的。我的印象是 HttpClient 现在在后台使用 Json.NET。也许我错了。我会找个修补匠,看看能找到什么。
  • 它似乎在后台使用 Json.NET - 请参阅下面 Jeff 的回答。
  • 好吧,我不知道。

标签: c# json serialization json.net


【解决方案1】:

JsonPropertyAttribute 属性的ItemConverterType 属性是用于集合项的转换器。您应该使用JsonConverterAttribute 属性。

public class TestData
{
    [JsonConverter(typeof(StringEnumConverter))]
    public TestEnum Enum { get; set; }
}

【讨论】:

  • 这行得通,谢谢!您是否知道为什么 DefaultSettings 也不起作用?如果可能的话,我宁愿不必用序列化属性来装饰我的类,但如果必须的话,我会的。再次感谢。
  • 假设 Json.net 实际上正在执行序列化,而不是 PostAsJsonAsync() 方法中使用的默认序列化程序,它应该可以正常工作。如果无法覆盖要使用的序列化程序,使用 Json.net 序列化可能更容易,然后发布结果字符串。
  • @JeffMercado 在您的回答中,“TestEnum”和“Enum”的顺序是否应该颠倒?
  • @Alex:不,TestEnum 是属性类型的名称。 Enum 是属性的名称。如果它们被颠倒(?),那么它们将具有非常不同的含义。
【解决方案2】:

我想我已经找到了一种不用装饰属性就能让它工作的方法。它涉及将client.PostAsJsonAsync() 替换为client.PostAsync()。然后,您可以指定要使用的 MediaTypeFormatter,在本例中为 JsonMediaTypeFormatter

来源:.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;

这仍然不能解释为什么没有应用 DefaultSettings。我只能假设[JsonConverter]属性的存在迫使HttpClient使用Json.NET进行序列化,否则它只使用默认的序列化程序。

【讨论】:

  • DefaultSettings 未应用,因为PostAsJsonAsync 调用new JsonMediaTypeFormatter() 创建JsonSerializerSettings 的新实例并绕过默认设置。这是错误的和烦人的。
  • 这是设计使然还是错误?
  • 为我工作。谢谢
猜你喜欢
  • 1970-01-01
  • 2021-06-04
  • 2022-01-24
  • 2015-05-11
  • 2020-05-15
  • 2014-10-31
  • 2018-02-12
  • 2014-01-20
  • 2015-01-13
相关资源
最近更新 更多