7

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

// When it was a string...
{
    someField: "some <span>html</span> string"
}

// When it became an IHtmlString...
{
    someField: { }
}

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

4

2 回答 2

8

背景

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

有了它,将你的 new 实例发送IHtmlStringConverter到 Json.NET 的SerializeObject调用。

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

示例代码

对于一个控制器演示的示例 MVC 项目,请访问此问题的 GitHub 存储库

于 2012-07-05T18:31:20.473 回答
0

上面的答案没有通过将 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 添加接口检查。

于 2017-03-01T17:01:23.660 回答