How do I serialize IHtmlString to JSON with Json.NET?

你离开我真会死。 提交于 2019-12-05 08:46:41
patridge

Background

Both Json.NET and the default .NET JavaScriptSerializer will treat instances of IHtmlString as an object with no properties and serialize it into an empty object. Why? Because it is an interface with only one method and methods don't serialize to JSON.

public interface IHtmlString {
    string ToHtmlString();
}

Solution

For Json.NET, you will need to create a custom JsonConverter that will consume an IHtmlString and output the raw string.

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

With that in place, send an instance of your new IHtmlStringConverter to Json.NET's SerializeObject call.

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

Sample Code

For an example MVC project where a controller demos this, head over to this question's GitHub repository.

The answer above is not taking the type into consideration by changing ReadJson into the code below should fix that. reference: 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);

Update: Adding a interface check to IHtmlString.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!