Stringify date in javascript in valid .Net format - javascript

I have a JSON object on client side that I want to get back on server side.
To do so, I have a hidden in which I put the stringified version of my object.
$("#<%=hidden.ClientID%>").val(JSON.stringify(obj));
Then, on server side, I try to deserialize it with JavaScriptSerializer.
My Problem : the stringified object contains a date and I can't parse it with de JavaScriptSerializer.
What I have done : Modify the date format to make it fit with the .Net format :
function FormatDate(date) {
if (typeof (date.getTime) != "undefined") {
return '\\/Date(' + date.getTime() + ')\\/'
}
return date;
}
Which seems to give a good format, but, when I use JSON.stringify on the object with the well formatted dates, it adds an extra backslash, so the JavaScriptSerializer still can't get it.
Any idea on how I could get it in a valid format in the hidden?

I had the same Problem and
'\/Date(' + date.getTime() + ')\/';
works for me.
You just have a double backslash instead of only one backslash.

I use the code below to fix the data after serializing.
var data = JSON.stringify(object);
data = data.replace(/\\\\/g, "\\");

Old question but in case someone arrives here like me looking for a solution, found this that works:
https://stackoverflow.com/a/21865563/364568
function customJSONstringify(obj) {
return JSON.stringify(obj).replace(/\/Date/g, "\\\/Date").replace(/\)\//g, "\)\\\/")
}

Related

JSON.parse - How to handle capitalized Boolean values?

I am working on a Node.js application that needs to handle JSON strings and work with the objects.
Mostly all is well and JSON.parse(myString) is all I need.
The application also gets data from third parties. One of which seems to be developed with Python.
My application repeatable chokes on boolean values since they come captialized.
Example:
var jsonStr = "{'external_id': 123, 'description': 'Run #2944', 'test_ok': False}";
try{
var jsonObj = JSON.parse(jsonStr);
}catch(err){
console.err('Whoops! Could not parse, error: ' + err.message);
}
Notice the test_ok parameter - it all is good when it follows the Javascript way of having a lower case false boolean instead. But the capitalized boolean does not work out.
Of course I could try and replace capitalized boolean values via a string replace, but I am afraid to alter things that should not get altered.
Is there an alternative to JSON.parse that is a little more forgiving?
I don't mean to be rude but according to json.org, its an invalid json. That means you'll have to run a hack where you have to identify stringified boolean "True" and convert it to "true" without affecting a string that lets say is "True dat!"
First of all, I would not recommend using the code below. This is just to demonstrate how to convert your input string into a valid JSON. There were problems, one is the Boolean False, and another is the single quotes around property names. I'm not positive but I believe those need to be double quotes.
I don't believe having to convert a string into a valid JSON is a good choice. If you have no alternative, meaning you don't have access to the code generating this string, then the code below is still not a good choice because it will have issues if you have embedded quotes in the string values. i.e. you would need different string replace logic.
Keep all this in mind before using the code.
var jsonStr = "{'external_id': 123, 'description': 'Run #2944', 'test_ok': False}";
try {
jsonStr = jsonStr.replace(/:[ ]*False/,':false' ).replace( /'/g,'"');
var jsonObj = JSON.parse(jsonStr);
console.log( jsonObj );
} catch (err) {
console.err('Whoops! Could not parse, error: ' + err.message);
}

Parsing date in Json Encoded array

I have built a MVC site and I am passing in my model to the view and attempting to use it in some javascript in the view using:
var records = #Html.Raw(Json.Encode(Model));
I am aiming on using these records in a custom calendar object that accepts an object array as a datasource. However, the datasource expects date variables to know where to put appointments etc. I've read that Json does not have any date format of it's own. So, all the dates that are returned from the encode are formatted like:
/Date(1462921200000)/
The object doesn't seem to accept this and nothing is shown on the view. In the posts that I've read they have stated that you can parse the date back into the correct format but this seems to be only on individual values.
My question is: is there an easy way to take the encoded object I've got and parse the dates into the correct format? Or would I have to loop through them in order to do it?
Thanks.
Warning: This answer is opinionated.
The opinionated part is: when you need something done with Json, use Json.Net.
namespace System.Web.MVC
{
public static class HtmlHelperJsonExtensions
{
public string JsonEncode(this System.Web.MVC.HtmlHelper html, object o)
{
var jsonSettings = new Newtonsoft.Json.JsonSerializerSettings()
{
// Here you can apply a LOT of formatting, as a small example regarding dates:
// 1 - formats dates as iso strings (probably what you want)
DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat,
// 2 - formats dates with Microsoft format (what you're experiencing)
//DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat,
// 3 - formats date in a custom format as for DateTime.ToString(string) overload
//DateFormatString = "yyyy-MM-dd"
Formatting = Indented
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(o, jsonSettings);
return html.Raw(json);
}
}
}
Usage:
var records = #Html.JsonEncode(Model);
Refer to the excellent Json.Net documentation here for insights.
Asp.Net MVC application return the dates in the ISO-8601 format by default.
You can convert the value in the client side with a function like this:
function ConvertDate(dateString) {
return new Date(parseInt(dateString.replace("/Date(", "").replace(")/", ""), 10));
}
Or you can use a library like momentjs (https://momentjs.com/docs/#/parsing/asp-net-json-date/):
moment("/Date(1198908717056-0700)/"); // 2007-12-28T23:11:57.056-07:00
Disclaimer: question was not identified as ASP.NET when I composed this answer. I presume the OP is asking for some feature provided by his yet to be disclosed framework. I keep the answer because I think it's valid for manual decoding in vanilla JavaScript.
The format can be parsed with a simple regular expression
var asText = "Date(1462921200000)";
var asDate = null;
var parsed = asText.match(/^Date\((\d+)\)$/);
if (parsed!==null) {
asDate = new Date(+parsed[1]);
}
console.log(asDate);

Parse ill formed JSON string

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 '":'.

Is JSON.parse supposed to be recursive?

I am parsing a json string like so:
ring = JSON.parse(response);
Now, ring is an object but ring.stones is just a string when it should be an object as well.
If I call:
ring.stones = JSON.parse(ring.stones);
It is now the correct object.
I didn't know if this is correct behavior or if maybe I have an issue somewhere stopping it from parsing recursively? If it is supposed to parse recursively, are there any known issues that would prevent it?
Update
Here is the full response before parsing:
{"ring_id":"9","stone_count":"4","style_number":"style 4","syn10":"436.15","gen10":"489.39","syn14":"627.60","gen14":"680.85","available":"yes","type":"ring","engravings_count":"0","engravings_char_count":"0","engravings_band":"10","stones":"[{\"stone_id\":\"27\",\"ring_id\":\"9\",\"stone_shape\":\"round\",\"stone_x\":\"132.80\",\"stone_y\":\"114.50\",\"stone_width\":\"71.60\",\"stone_height\":\"71.60\",\"stone_rotation\":\"0.00\",\"stone_number\":\"1\",\"stone_mm_width\":\"5.00\",\"stone_mm_height\":\"5.00\"},{\"stone_id\":\"28\",\"ring_id\":\"9\",\"stone_shape\":\"round\",\"stone_x\":\"100.50\",\"stone_y\":\"166.20\",\"stone_width\":\"36.20\",\"stone_height\":\"36.60\",\"stone_rotation\":\"0.00\",\"stone_number\":\"2\",\"stone_mm_width\":\"2.50\",\"stone_mm_height\":\"2.50\"},{\"stone_id\":\"29\",\"ring_id\":\"9\",\"stone_shape\":\"round\",\"stone_x\":\"200.20\",\"stone_y\":\"105.10\",\"stone_width\":\"33.90\",\"stone_height\":\"33.90\",\"stone_rotation\":\"0.00\",\"stone_number\":\"3\",\"stone_mm_width\":\"2.50\",\"stone_mm_height\":\"2.50\"},{\"stone_id\":\"30\",\"ring_id\":\"9\",\"stone_shape\":\"round\",\"stone_x\":\"165.80\",\"stone_y\":\"82.50\",\"stone_width\":\"35.50\",\"stone_height\":\"33.90\",\"stone_rotation\":\"0.00\",\"stone_number\":\"4\",\"stone_mm_width\":\"2.50\",\"stone_mm_height\":\"2.50\"}]","images":"[{\"title\":\"white gold\",\"source\":\"Style4_4_W_M.png\"},{\"title\":\"yellow gold\",\"source\":\"Style4_4_Y_M.png\"}]"}
Update 2
Based on mikerobi's answer I was able to figure out what was happening:
Here is where I encoded it:
$row = $sth->fetch(PDO::FETCH_ASSOC);
$row['stones'] = getStones($ring_id);
$row['images'] = getRingVariations($ring_id);
return json_encode($row);
But the functions getStones and getRingVariations were returning json_encode'd strings. I needed to change them to return plain strings.
Your JSON structure is wrong, it is wrapping stones in quotes, turning it into a string.
Your JSON looks like:
{
stones: "[{\"stone_id":\"27\"},{\"stone_id\":\"27\"}]"
}
It should look like:
{
stones: [{"stone_id": 27},{"stone_id": 27}]
}
EDIT
It appears you are converting all values to string, including numbers, I updated my example to reflect this.
Also, I'm guessing by the output that you are writing your own code to serialize the JSON, I highly recommend using an existing library.
It is recursive, but your input string (response) is not in correct format. Get rid of those escape characters (\") and try again.

Dash in date format and get method

I have asp (classic) script and within javascript code. From database I get date in format yyyy-mm-dd (2010-10-14) and save in variable. Then, I pass this variable to javascript method:
Response.Write("<a href='Javascript: PassDate("&OurDate&","&Val1&","&Val2&");'>Pass</a>")
This method code is:
function PassDate(OurDate, Val1, Val2)
{
window.open("newsite.asp?date="+OurDate+"&val1="+Val1+"&val2="+Val2");
}
When I try get date on new site (newsite.asp) by Request.QueryString("date"), I get calculate value 1996 (2010-10-14 = 1986), instead date '2010-10-14'.
I try various ways to solve this problem, but it still calculate value.
For example, I try replace "-" for ".", but I get error about missing ")".
Use commas instead of dashes. That way, each part will be seen as a separate argument to the JavaScript function.
Have you considered saving the date using the javascript date object and then passing that to your method?
My javascript is a little rusty, but I believe it would be something like the following:
var dateParts = split(OurDate, "-");
var myDate = new Date(dateParts[0], dateParts[1], dateParts[2]);

Categories