如何使用Json.NET将IHtmlString序列化为JSON?

我有一个字段包含通过JSON发布的原始HTML,最近从字符串转换为IHtmlString。 当发生这种变化时,该字段从一个JSON字符串变为一个空对象,并且消耗了JSON开始爆炸的一堆东西。

// When it was a string... { someField: "some html string" } // When it became an IHtmlString... { someField: { } } 

忽略JSON中原始HTML的任何参数,因为这个项目没有实际意义,我如何在我的JSON序列化中获得预期的字符串?

背景

Json.NET和默认的.NET JavaScriptSerializer都将IHtmlString实例视为没有属性的对象,并将其序列化为空对象。 为什么? 因为它是只有一个方法的接口,所以方法不会序列化为JSON。

 public interface IHtmlString { string ToHtmlString(); } 

对于Json.NET,您需要创建一个自定义JsonConverter ,它将使用IHtmlString并输出原始字符串。

 public class IHtmlStringConverter : Newtonsoft.Json.JsonConverter { public override bool CanConvert(Type objectType) { return typeof(IHtmlString).IsAssignableFrom(objectType); } public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { IHtmlString source = value as IHtmlString; if (source == null) { return; } writer.WriteValue(source.ToString()); } public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { // warning, not thoroughly tested var html = reader.Value as string; return html == null ? null : System.Web.Mvc.MvcHtmlString.Create(html); } } 

有了这个,将新的IHtmlStringConverter实例发送到Json.NET的SerializeObject调用。

 string json = JsonConvert.SerializeObject(objectWithAnIHtmlString, new[] { new IHtmlStringConverter() }); 

示例代码

对于控制器演示此示例的MVC项目,请转到此问题的GitHub存储库 。

上面的答案是不考虑将类型考虑在内,将ReadJson更改为下面的代码应该解决这个问题。 参考: https : //sebnilsson.com/blog/serialize-htmlstring-mvchtmlstring-in-json-net/

 var value = reader.Value as string; // Specifically MvcHtmlString if (objectType == typeof(MvcHtmlString)) { return new MvcHtmlString(value); } // Generally HtmlString if (objectType == typeof(HtmlString)) { return new HtmlString(value); } if (objectType.IsInterface && objectType == typeof(IHtmlString)) { return new HtmlString(value); } // Fallback for other (future?) implementations of IHtmlString return Activator.CreateInstance(objectType, value); 

更新:向IHtmlString添加接口检查。