Ваша основная проблема в том, что 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
обратно в экземпляр LogLevel
.
Тем не менее, ваш образец JSON представляет Level
как "level": "Error"
, и поэтому отправляющая система, должно быть, использовала какой-то custom JsonConverter
для LogLevel
, который сериализует только LogLevel.Name
, Мы можем легко создать такой JsonConverter
следующим образом:
public class LogLevelConverter : JsonConverter<LogLevel>
{
public override LogLevel ReadJson(JsonReader reader, Type objectType, LogLevel existingValue, bool hasExistingValue, JsonSerializer serializer)
{
switch (reader.MoveToContentAndAssert().TokenType)
{
case JsonToken.Null:
return null;
case JsonToken.String:
return LogLevel.FromString((string)reader.Value);
default:
throw new JsonSerializationException(string.Format("Unknown token {0}", reader.TokenType));
}
}
public override void WriteJson(JsonWriter writer, LogLevel value, JsonSerializer serializer)
{
var logLevel = (LogLevel)value;
writer.WriteValue(logLevel.Name);
}
}
public static partial class JsonExtensions
{
public static JsonReader MoveToContentAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (reader.TokenType == JsonToken.None) // Skip past beginning of stream.
reader.ReadAndAssert();
while (reader.TokenType == JsonToken.Comment) // Skip past comments.
reader.ReadAndAssert();
return reader;
}
public static JsonReader ReadAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (!reader.Read())
throw new JsonReaderException("Unexpected end of JSON stream.");
return reader;
}
}
А затем используйте его следующим образом:
var seq = new LogLevelConverter();
var info = Newtonsoft.Json.JsonConvert.DeserializeObject<LogEventInfo>(msg.Body, seq);
Демонстрационная скрипка здесь .