我在反序列化枚举时遇到问题

时间:2019-06-05 05:17:00

标签: c# json.net nlog

我正在使用NLog,并且正在通过导线发送LogEventInfo对象,我不拥有该对象,因此无法使用[JsonConverter(typeof(StringEnumConverter))]装饰它,或者也许可以,我只是不知道如何

我尝试了以下代码,但没有帮助

var strategy = new Newtonsoft.Json.Serialization.CamelCaseNamingStrategy();
var sec = new StringEnumConverter(strategy, false);

//TEMP Hard code serialization and message routing for just logs
LogEventInfo info = Newtonsoft.Json.JsonConvert.DeserializeObject<LogEventInfo>(msg.Body, sec);

有人有幸得到枚举进行反序列化并且枚举属于您不拥有的课程吗?

以下是消息:

{
   "date":"2019-06-04 21:48:24.0753",
   "level":"Error",
   "message":"{\"ApplicationId\":1390760,\"AppStatus\":\"#PG2\",\"Status\":400,\"ErrorCode\": 1053 }",
   "properties":"ResponseBody={\"ApplicationId\":1390760,\"AppStatus\":\"#PG2\",\"Status\":400,\"ErrorCode\": 1053 }|GroupId=392934|ApplicationId=1390760|Status=400",
   "callsite":"HFD.Enterprise.Logging.Tests.LogTest.LoadTest",
   "logger":"WebApiLog",
   "machinename":"BRANDONHOSTVS"
}

这是个例外:

Newtonsoft.Json.JsonSerializationException: Error converting value "Error" to type 'NLog.LogLevel'. Path 'level', line 1, position 72. ---> System.InvalidCastException: Invalid cast from 'System.String' to 'NLog.LogLevel'.
   at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   at System.String.System.IConvertible.ToType(Type type, IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
   --- End of inner exception stack trace ---

1 个答案:

答案 0 :(得分:4)

您的基本问题是LogEventInfo.Level不是枚举,它是LogLevel类,恰好实现IConvertible并具有一组全局静态变量标准值:

public sealed class LogLevel : IComparable, IEquatable<LogLevel>, IConvertible
{
    /// <summary>
    /// Gets all the available log levels (Trace, Debug, Info, Warn, Error, Fatal, Off).
    /// </summary>
    public static IEnumerable<LogLevel> AllLevels => allLevels;

添加StringEnumConverter不会帮助您反序列化此类属性。

此外,NLog似乎没有为TypeConverter提供自定义LogLevel。如果我调用TypeDescriptor.GetConverter(typeof(LogLevel)),则返回的值是默认转换器System.ComponentModel.TypeConverter的实例,这意味着Json.NET无法将序列化的LogLevel字符串值转换回{{1} }实例。

尽管如此,您的JSON示例确实将LogLevel表示为Level,所以发送系统必须一直在"level": "Error"使用某种custom JsonConverter来仅对{{ 1}}。我们可以很容易地重新创建这样的LogLevel,如下所示:

LogLevel.Name

然后按如下所示使用它:

JsonConverter

演示小提琴here