Serializing strings containing apostrophes with JSON.Net
Asked Answered
D

5

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?

Dorton answered 20/8, 2012 at 17:35 Comment(5)
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.Petta
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.Dorton
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.Petta
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.Dorton
Well that was a good guess it seems :-) I'll type it in.Petta
P
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.

Petta answered 20/8, 2012 at 23:1 Comment(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));Blowsy
C
31
JsonSerializerSettings settings = new JsonSerializerSettings
{
    StringEscapeHandling = StringEscapeHandling.EscapeHtml
};

JsonConvert.SerializeObject(obj, settings);
Caraviello answered 9/1, 2015 at 11:41 Comment(0)
C
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());
Calyx answered 20/8, 2012 at 18:24 Comment(2)
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.Dorton
this was good for fixing single quote breaking my sql statement. I just changed the replace part to Replace("'", "''").Blessed
P
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.

Petta answered 20/8, 2012 at 23:1 Comment(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));Blowsy
E
4

Use System.Web.HttpUtility.HtmlEncode

HttpUtility.HtmlEncode(JsonConvert.SerializeObject(myObject))
Enabling answered 1/5, 2014 at 16:52 Comment(1)
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.Jerricajerrie
H
0

With .NET 8 here is an 'unsafe' solution to produce indented, sparsely escaped JSON.

I get trying to be safe and use standards, but the level of escaping with apostrophes makes the JSON text elements not editable. And if you have any markup in those strings, that is a huge mess.

var options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    WriteIndented = true
};

jsonString = JsonSerializer.Serialize(myJsonObject, options);

See the warning here: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/character-encoding#serialize-all-characters

BTW: I tried to not escape just the characters I wanted to leave based on a note on the same page, but it didn't work.

Hothead answered 22/3 at 14:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.