1

I am serialising an array in ASP using JsonConvert.SerializeObject. The arrays contain text including symbols such as single quotation marks. The conversion works OK until I try to parse it in JavaScript using JSON.parse. It fails when it gets the single quotation mark. I want to avoid removing the single quotation marks manually if possible.

Here is the MVC code:

SheetsArr = JsonConvert.SerializeObject(Sheets);

Here is the JS code:

var SheetsArr = JSON.parse('@Html.Raw(@Model.Sheets)');

This is the error message in Chrome:

Uncaught SyntaxError: missing ) after argument list

dave88
  • 312
  • 5
  • 14
  • 2
    You'll need to escape any special characters inside your string if you are passing it as JSON and trying to parse it. I don't believe the single quotes should be a problem, this post lists the special characters that need escaped: (https://stackoverflow.com/questions/19176024/how-to-escape-special-characters-in-building-a-json-string) – Ryan Wilson Jun 06 '19 at 13:52
  • You can use backtick (``) character within value of JSON.parse for special characters – Abdulsamet Kurt Jun 06 '19 at 14:06
  • I'm not sure what is exactly meant by escaping special characters. Would this be when the JSON has been converted in the controller to iterate over every character in the string and replace the special chars? – dave88 Jun 06 '19 at 14:16

2 Answers2

3

Instead of trying to treat the data as a string in the JS and parsing it again, you can just inject the value direct into the JS as an array literal. Since JSON is a subset of JS object literal syntax, it'll just be treated as a literal. Don't think you even need the Html.Raw() command.

Try simply

var SheetsArr = @Model.Sheets;

(I'm assuming here that in the C# you assigned the C# SheetsArr variable to the Sheets property of your model before you returned it.)

Then this removes the issue where your single-quoted string in JS is mucked up by single quotes within the JSON string.

To illustrate the point, let's say that Model.Sheets contains a JSON string like this:

[{ "SomeProp": "Hello, 'Friend'"}, { "SomeProp": "Hello again"}]

You can see the single quote marks.

In your original code, executing the Razor code with that string in it would result in the following JavaScript:

var SheetsArr = JSON.parse('[{ "SomeProp": "Hello, 'Friend'"}, { "SomeProp": "Hello again"}]');

As you can see, the single quotes in the middle are now a problem because they terminate the outer string literal quotes.

Whereas if we just inject the JSON directly in the way I've suggested, the resulting JS is this (I've added the console command just so you can see the result):

var SheetsArr = [{ "SomeProp": "Hello, 'Friend'"}, { "SomeProp": "Hello again"}];
console.log(SheetsArr);
ADyson
  • 57,178
  • 14
  • 51
  • 63
  • 1
    This method worked out to be most consistent. It got to a point where I was pulling the data down using a XHR, but then thinking what's the point of MVC. It seems a lot of my projects are MVC/SPA hybrid. The MVC is the initial load and XHR takes care of logging changes. – dave88 Jun 07 '19 at 10:52
  • @dave88 glad it worked for you. I also do this kind of injection a fair bit - allows you to have data ready in the JS when the page loads. As you say, it avoids an extra AJAX call to fetch it separately. And I've found that just injecting it as a literal in this way is by far the easiest and most reliable way, as well as involving the least amount of code. [KISS](https://en.wikipedia.org/wiki/KISS_principle)! – ADyson Jun 07 '19 at 10:55
-1

We essentially do this in our app to achieve the same thing

In the controller:

var serializerSettings = new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver(),
};
modal.Sheets = JsonConvert.SerializeObject(Sheets, serializerSettings);

In the view:

var SheetsArr = "@Html.Raw(@Model.Sheets.Replace("\"", "\\\""))");
Chris Barr
  • 29,851
  • 23
  • 95
  • 135
  • This doesn't quite "achieve the same thing" in actual fact. In your code, the JS `sheetsArr` variable will be a string, not an object. It would still need parsing in order to be useful. The goal, per the question, is to produce an object (or technically, an array in this case, but certainly not a string). – ADyson Jun 07 '19 at 10:53
  • No, in our code it's a JSON object that we push into session storage. I just changed the variable names here to be relevant to your code. I suppose now that I look at I see that we are just escaping double quotes all over and not doing anything with single quotes, so I see your point. – Chris Barr Jun 07 '19 at 13:16
  • It's not my code, I didn't ask the question :-). But anyway, in your example you wouldn't _need_ to do anything with single quotes, because the outer string literal is wrapped in doubles, so only double-quotes within the string could break it. But my point was not really that there's anything wrong with your code as such, just that it doesn't quite do what the question requested. – ADyson Jun 07 '19 at 13:38