7

最近文字列から IHtmlString に変換された JSON 経由で公開された生の HTML を含むフィールドがあります。その変更が発生したとき、フィールドは 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プロパティのないオブジェクトとして扱い、空のオブジェクトにシリアル化します。なんで?これは、メソッドが 1 つしかないインターフェイスであり、メソッドが 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 に答える