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

I have a field containing the original HTML published via JSON, which was recently converted from a string to IHtmlString. When this change occurred, the field went from a JSON string to an empty object and a bunch of things consuming JSON that started to explode.

// 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 as it is controversial for this project, how do I get the expected string in my JSON serialization?

+6
source share
2 answers

Background

Both Json.NET and standard JavaScriptSerializer, by default, process IHtmlString instances as an object with no properties and serialize it to an empty object. What for? Since this is an interface with only one method, and the methods are not serialized in JSON.

 public interface IHtmlString { string ToHtmlString(); } 

Decision

For Json.NET, you need to create a custom JsonConverter that will consume IHtmlString and output the original 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); } } 

In doing so, send an instance of your new IHtmlStringConverter call to Json.NET SerializeObject .

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

Code example

For an example MVC project where the controller demonstrates this, go to this question on the GitHub repository .

+6
source

The answer above does not account for the type by changing ReadJson to the code below to fix this. link: 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 interface validation to IHtmlString.

0
source

Source: https://habr.com/ru/post/919797/


All Articles