JSON反序列化为自定义LogItem类型时遇JsonReaderException错误
问题原因
JSON中的Properties是一个嵌套的对象结构(用{}包裹),但你定义的LogItem类里将Properties声明为string类型,Newtonsoft.Json无法将对象直接转换为字符串,因此抛出JsonReaderException错误。
解决方案
提供三种可行的解决方式,根据你的需求选择:
方式一:将Properties改为JObject类型
直接用JObject接收JSON对象,后续可按需转为字符串或访问内部属性:
public class LogItem { public DateTimeOffset Timestamp { get; set; } public string Level { get; set; } public string MessageTemplate { get; set; } public JObject Properties { get; set; } // 替换为JObject类型 public string SourceContext { get; set; } }
反序列化后,若需要将Properties转为字符串,可调用:
string propertiesStr = obj2.Properties.ToString(Formatting.None);
方式二:自定义转换器将对象转为字符串
如果必须将Properties存储为string,可以编写自定义JSON转换器实现对象与字符串的互转:
- 定义转换器类:
public class ObjectToStringConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(string); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.StartObject) { var jObj = JObject.Load(reader); return jObj.ToString(Formatting.None); } return reader.Value?.ToString(); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value is string jsonStr) { var jObj = JObject.Parse(jsonStr); serializer.Serialize(writer, jObj); } else { serializer.Serialize(writer, value); } } }
- 在
LogItem的Properties属性上添加转换器特性:
public class LogItem { public DateTimeOffset Timestamp { get; set; } public string Level { get; set; } public string MessageTemplate { get; set; } [JsonConverter(typeof(ObjectToStringConverter))] public string Properties { get; set; } public string SourceContext { get; set; } }
方式三:创建匹配Properties结构的类
如果需要直接访问Properties内部的字段,可以定义对应的实体类来匹配JSON结构:
public class EventId { public int Id { get; set; } public string Name { get; set; } } public class LogProperties { public string FullName { get; set; } public EventId EventId { get; set; } public string SourceContext { get; set; } } public class LogItem { public DateTimeOffset Timestamp { get; set; } public string Level { get; set; } public string MessageTemplate { get; set; } public LogProperties Properties { get; set; } public string SourceContext { get; set; } }
反序列化后可直接通过obj2.Properties.FullName、obj2.Properties.EventId.Id等方式访问内部属性。
内容的提问来源于stack exchange,提问作者buga
相关产品推荐
相关产品推荐

