Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

json

c#

json.net

I have a field containing raw HTML published via JSON that was recently converted from a string to an IHtmlString. When that change happened, the field went from being a JSON string to being an empty object and a bunch of things consuming that JSON started blowing up.

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

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

Ignoring any arguments against raw HTML in JSON since it is moot for this project, how do I get the expected string in my JSON serialization?

like image 779
patridge Avatar asked Jul 05 '12 18:07

patridge


People also ask

Can you serialize a list in JSON?

Can JSON serialize a list? Json.NET has excellent support for serializing and deserializing collections of objects. To serialize a collection - a generic list, array, dictionary, or your own custom collection - simply call the serializer with the object you want to get JSON for.

How do you serialize and deserialize an object in C# using JSON?

It returns JSON data in string format. In Deserialization, it does the opposite of Serialization which means it converts JSON string to custom . Net object. In the following code, it calls the static method DeserializeObject() of the JsonConvert class by passing JSON data.

Does JSON net serialize private fields?

Private and protected members are not serialized.


1 Answers

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.

like image 186
patridge Avatar answered Nov 14 '22 22:11

patridge