So, I have a some json data which I create in my controller like so:
Notes = JsonConvert.SerializeObject(contact.Notes.OrderBy(x => x.DateLogged).Select(x => new
{
id = x.Id,
date = x.DateLogged,
content = x.Content,
logged = x.Username
}))
This then gets passed to the view, now which statment can I do to achieve the results of having a variable contain that json data:
var data = '#Html.Raw(Model.Notes)'
or
var data = JSON.parse('#Html.Raw(Model.Notes)');
EDIT
the content variable holds some "\n" which when passed to the view using the first choice from above generates an error, saying
Unexpected Token
it only does it with \n so what is going wrong here? the bottom method doesn't quite work.
var data = JSON.parse('#Html.Raw(Model.Notes)');
This doesn't work - you can't put a JSON literal inside a JavaScript string. Any backslash in it will be an escape character to the JavaScript parser, not the JSON parser. A newline comes out like:
var data = JSON.parse('{"content": "abc\ndef"}');
which means the string you are asking JSON to parse is:
{"content": "abc
def"}
which is not valid as you can't have a literal newline in a JSON string.
To do this with JSON.parse you would have to JS-string-literal encode the JSON output, so you would end up with "abc\\ndef". The alternative would be to include the JSON directly in the script block as var data = #Html.Raw(Model.Notes);, but there are problems with this to do with the differences between JS and JSON (primarily characters U+2028 and U+2029) and the enclosing HTML context (ie what the sequence </script does).
Getting the escaping right here is harder than it looks, so you should avoid injecting anything into a <script> block. Better to put in-page JSON data in a data- attribute and read it from the DOM; this way you can use the normal HTML escaping Razor gives you by default.
<div id="notes" data-notes="#Model.Notes">
...
var data = JSON.parse(document.getElementById('notes').getAttribute('data-notes'));
bobince is obviously correct in what he says, it makes so much sense, thanks for that.
However, my solution was to simply do:
var data = #Html.Raw(Model.Notes);
Because, Newtonsoft already has converted it to a proper JSON format, so all it needs to do, is be assigned to a variable to be manipulated.
I think grabbing the content from a the HTML DOM is a bit too much for this.
Related
Consider the following event payload data returned via WS:
{
id: "1",
foo: "{"bar":"baz"}"
}
The current output of JSON.stringify(event.foo):
"{\"bar\":\"baz\"}"
Also consider the backend have no real way to return the foo value formatted differently and I need to find a way to parse the string associated to this foo key in order to access it's value of bar.
The identified problem is the fact that the quotes used to wrap the whole supposed object are the sames used in the object itself, resulting in making JSON.parse() impossible.
I'm wondering if there is a "clean" way to achieve this.
So far, I tried:
using JSON.parse() which fails due to the format of the string raising Unexpected end of JSON input
trimming external quotes and converting inner ones to single then parsing, results in same error.
using new Object(...) based on the string (trimmed of external quotes)
replacing all quotes with single ones and wrapping it again in double ones to parse it.
Any input appreciated
The problem here is the backend should really be fixed, but some reason you can not do it. Next issue is you can "fix it" on the front end, but you are putting a band aid on the problem and it will fall off when the data that comes back is not what you expect. So the solutions will be error prone unless you know the data coming back will be a specific type.
With this said, you can fix the invalid JSON that you have in your simple example with a couple of regular expressions. Problem is, if your data contains characters such as } in the text, this is going to fail.
var response = `
{
id: "1",
foo: "{"bar":"baz"}",
goo: "{"gar":"gaz"}"
}
`
var reObj = /"(\{[^}]*})"/
while (response.match(reObj)) {
response = response.replace(reObj, '$1')
}
var reKey = /^\s+(\S+):/m
while (response.match(reKey)) {
response = response.replace(reKey,'"$1":')
}
var obj = JSON.parse(response)
console.log(obj)
This is what I send to my controller:
"[{\"PropertyName\":\"fewfewf\",\"Key\":\"ewgwewe\",\"PrimaryValue\":\"\",\"SecondaryValue\":\"\",\"TertiaryValue\":\"\",\"MinimumValue\":\"\",\"MaximumValue\":\"\"},{\"PropertyName\":\"rwhjyjut\",\"Key\":\"jtyjyt\",\"PrimaryValue\":\"\",\"SecondaryValue\":\"\",\"TertiaryValue\":\"\",\"MinimumValue\":\"\",\"MaximumValue\":\"\"}]"
This is what I receive back from the server after I parse and serialize it again.
I am very confused as I haven't changed anything. When I try to parse it Jquery side, I get this error:
Uncaught SyntaxError: Unexpected token & in JSON at position 2
This is the jquery code
if ("#Model.FormPropertiesList".length !== 0) {
console.log($.parseJSON("#Model.FormPropertiesList"));
}
Am i Missing something?
EDIT: This is my serverside code
var list = JsonConvert.DeserializeObject<List<NewFormPropertyViewModel>>(Input.FormPropertiesList);
Input.FormPropertiesList = JsonConvert.SerializeObject(list);
return View("Create", Input);
This is how i convert the string to JSON
$("##Html.IdFor(m => m.FormPropertiesList)").val(JSON.stringify(dataSet));
The string is being HTML encoded. You can use #HTML.Raw to tell razor to put the string as is. One of the reasons strings get encoded is for security purposes. Say you are trying to display some data you just fetched from a database and that data has some "malicious" JavaScript, while this code will be harmless to the database, it will affect the client once the view is rendered. You can try:
if ("#Model.FormPropertiesList".length !== 0) {
console.log(JSON.parse("#HTML.Raw(Model.FormPropertiesList)"));
}
First replace your """
var serverrep= "[{"PropertyName":"fewfewf","Key":"ewgwewe","PrimaryValue":"","SecondaryValue":"","TertiaryValue":"","MinimumValue":"","MaximumValue":""}]"
var serverRepWithoutQuots=serverrep.replace(/"/g, '"');
console.log(serverRepWithoutQuots)
console.log(JSON.parse(serverRepWithoutQuots))
I had an issue like this when passing JSON to my template then to my js file in Django. When you do this in Django you pass something from the view in the context, then when you're in the Django template you would do something like
var someName = {{ fromView }};
and I had it wrapped in doubles quotes
var someName = "{{ fromView }}";
so it was escaping the double quotes in the JSON that was parsed. I spent like 2 hours trying to figure out what was up and I literally had to just change the double quotes to single quotes because it was reading it as a string with double quotes that had another string(json string) with double quotes in it
var someName = '{{ fromView }}';
point being I would check the JSON to make sure you're not passing it the wrong way and it's being encoded improperly / adding extra quotes somewhere
I know this question has been asked numerous times, but I really donĀ“t get it.
I am creating a site in MVC, and I'm creating a JSON string from my model. I then want to pass it as argument to a JavaScript function that uses it to plot a graph.
Here is were I create the JSON string. This indeed creates a valid JSON string, I checked it at JSONLint.
#{
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var weightsAsJsonString = serializer.Serialize(Enumerable.Select(Model, weight =>
new
{
date = weight.Date,
value = weight.Value
}));
}
Further down I create a JavaScript variable from it and pass it into the JavaScript function:
var jsonStringToGraph = #weightsAsJsonString;
google.setOnLoadCallback(drawVisualization(jsonstring));
When I run this, the console prints 'SyntaxError: Unexpected token &' at the line were I declare jsonStringToGraph. I googled around and concluded that I should put ' ' around #weightsAsJsonString, so I do that.
Anyway, in my drawVisualization, I do this:
function drawVisualization(teststring) {
.......
var parsedJson = JSON.parse(teststring);
This gives me SyntaxError: Unexpected token & Index:1
I know that the code at the bottom is what is causing the exception, but I do not understand why. Do anyone understand what I am doing wrong?
Edit: This is the weightsAsJsonString
[{"date":"\/Date(1434492000000)\/","value":100.2},{"date":"\/Date(1434578400000)\/","value":99.2},{"date":"\/Date(1434664800000)\/","value":101.2},{"date":"\/Date(1434751200000)\/","value":98.2},{"date":"\/Date(1434837600000)\/","value":97.2},{"date":"\/Date(1434924000000)\/","value":96.2},{"date":"\/Date(1435010400000)\/","value":95.2},{"date":"\/Date(1435096800000)\/","value":94.2}]
It sounds like your issue is trying to inject content via Razor into JavaScript. By default # will HTML-encode your content, which doesn't work in the context of JavaScript.
#Html.Raw(weightsAsJsonString) will work better, and then your JS will have a JavaScript object, so there's no need for the JSON.parse later on.
When you do var jsonStringToGraph = #weightsAsJsonString; you are actually defining a JSON object and not a JSON string.
Hence when you do JSON.parse(teststring); you are trying to parse an object instead of a string.
Either put apostrophes around the first declaration var jsonStringToGraph = '#weightsAsJsonString'; or simply do not try to parse it again.
I am being sent an ill formed JSON string from a third party. I tried using JSON.parse(str) to parse it into a JavaScript object but it of course failed.
The reason being is that the keys are not strings:
{min: 100}
As opposed to valid JSON string (which parses just fine):
{"min": 100}
I need to accept the ill formed string for now. I imagine forgetting to properly quote keys is a common mistake. Is there a good way to change this to a valid JSON string so that I can parse it? For now I may have to parse character by character and try and form an object, which sounds awful.
Ideas?
You could just eval, but that would be bad security practice if you don't trust the source. Better solution would be to either modify the string manually to quote the keys or use a tool someone else has written that does this for you (check out https://github.com/daepark/JSOL written by daepark).
I did this just recently, using Uglifyjs to evaluate:
var jsp = require("uglify-js").parser;
var pro = require("uglify-js").uglify;
var orig_code = "var myobject = " + badJSONobject;
var ast = jsp.parse(orig_code); // parse code and get the initial AST
var final_code = pro.gen_code(ast); // regenerate code
$('head').append('<script>' + final_code + '; console.log(JSON.stringify(myobject));</script>');
This is really sloppy in a way, and has all the same problems as an eval() based solution, but if you just need to parse/reformat the data one time, then the above should get you a clean JSON copy of the JS object.
Depending on what else is in the JSON, you could simply do a string replace and replace '{' with '{"' and ':' with '":'.
First of all, I'm fairly new to json, so please forgive me if I've made a terrible mistake. I've got some code that gets a json object from a website using YQL It returns it as a string. So now I want to parse this into a json object and than read it.
This is my code:
$.getJSON("http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url=%22http://iphone-api.uitzendinggemist.nl/v1/episodes.json%22%20and%20xpath=%27*%27&format=json", function(data) {
console.log(data);
content = data.query.results.html.body.p;
json = JSON.stringify(eval("(" + content + ")"));
str = json.revoked;
$('#table').append('<li>' + str + '</li>');
});
JS fiddle
I just can't figure out why this gives me undifined, instead of the value it should give.
So now my question was if someone here knows why it isn't working properly.
The json variable is an array, you need to access an index.
string = json[0].revoked;
You have many many many errors in your code. You should try to understand each step that you are doing, it looks like you don't. Here's a fork of your code that does something, I'm not sure what you want it to do. I'll tell you few things you did wrong:
Use var keyword when declaring new variables within functions
Don't parse JSON using eval(), but use some parser. E.g. $.parseJSON(). Using eval() is a security risk, as returned script WILL be executed on client and you should only be interested in getting data.
When constructing HTML, take care to encode text that you want displayed. In your case, don't concatenate strings ('<li>' + str + '</li>'). You can use jQuery ($('<li>').text(str)).
Don't add li elements to a table element. Either add them to ul or ol elements, or in case of tables create rows and cells.
It is completely unclear why you would eval, and them stringify an object. You end up with same exact data.