21

I am using JSON.Net as my serializer for a large MVC 3 web application in c# and the Razor view engine. For the initial page load in one view, there is a large amount of JSON dumped inside a script tag using @Html.Raw(JsonConvert.SerializeObject(myObject)).

The problem is that some values of some objects contain apostrophes (think names like O'Brien), which JSON.Net is not escaping or encoding in any way.

It's not an option to pre-encode the values stored in the database because that vastly complicates various other processes.

Is there a way to force JSON.Net to HTML encode the values of the objects that it serializes, the same way that the built-in JavaScriptSerializer does when you call JavaScriptSerializer.Serialize(myObject)? Or, is there a way to deal with this in the view?

Jeroen
  • 60,696
  • 40
  • 206
  • 339
dodexahedron
  • 4,584
  • 1
  • 25
  • 37
  • Because JSON insists on double-quote characters for strings, there's nothing wrong with single-quote characters and there's no need to escape them. – Pointy Aug 20 '12 at 17:38
  • 2
    This is untrue. When you dump JSON into an HTML page, the JSON string itself is enclosed in either single or double quotes, which will make whichever character you used to wrap the string unusable within the JSON itself. THAT is the crux of the issue. – dodexahedron Aug 20 '12 at 19:11
  • 2
    Well if your "dumping" the JSON as a *string*, then that'd be a problem. Why don't you put it on the page as JavaScript - without any additional quotes, in other words? Otherwise you can just use a regex to quote the single-quotes. – Pointy Aug 20 '12 at 19:13
  • This is the solution. It's not necessary, as you point out, to put it in the page as a string. Make that response an answer and I'll accept it. – dodexahedron Aug 20 '12 at 22:43
  • Well that was a good guess it seems :-) I'll type it in. – Pointy Aug 20 '12 at 22:59

4 Answers4

31
JsonSerializerSettings settings = new JsonSerializerSettings
{
    StringEscapeHandling = StringEscapeHandling.EscapeHtml
};

JsonConvert.SerializeObject(obj, settings);
Tim S. Van Haren
  • 8,861
  • 2
  • 30
  • 34
rrymar
  • 310
  • 3
  • 4
18

You can create custom JsonConverter like this:

public class EscapeQuoteConverter : JsonConverter 
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    {
        writer.WriteValue(value.ToString().Replace("'", "\\'"));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    {
        var value = JToken.Load(reader).Value<string>();
        return value.Replace("\\'", "'");
    }

    public override bool CanConvert(Type objectType) 
    {
        return objectType == typeof(string);
    }
}

To use this only for Name property specify it by attribute:

public class Person 
{
    [JsonConverter(typeof(EscapeQuoteConverter))]
    public string Name { get; set; } 
}

To apply Converter to all strings use:

JsonConvert.SerializeObject(person, Formatting.Indented, new EscapeQuoteConverter());
Pavel Bakshy
  • 7,697
  • 3
  • 37
  • 22
  • This is a neat mechanism. Thanks for that. Pointy's comment was the "you're doing it wrong" I needed, though. Make than an answer and I'll mark it correct. – dodexahedron Aug 20 '12 at 19:48
  • this was good for fixing single quote breaking my sql statement. I just changed the replace part to Replace("'", "''"). – Alex Oct 08 '15 at 15:11
18

Though there are some cases wherein you might want to drop some JSON into your page as a JavaScript string, or an HTML attribute value, most often what you'd do is simply include it directly into JavaScript source, because JSON is valid JavaScript syntax after all.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • 1
    Correct! This means than instead of doing something like this for example: var myObject = JSON.parse('@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.MyObject))'); Do this: var myObject = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.MyObject)); – Xaris Fytrakis Jul 01 '16 at 15:32
4

Use System.Web.HttpUtility.HtmlEncode

HttpUtility.HtmlEncode(JsonConvert.SerializeObject(myObject))
Preston S
  • 2,751
  • 24
  • 37
  • Thanks, although this doesn't answer the question asked here, it did answer the question I asked on Google, with this being the first result. – Lunster Mar 04 '15 at 12:12