Dart: Parse JSON with comments - json

I already tried to filter them out before parsing, but the Problem is, that it is possible to have "//", "/*" and "*/" inside a value, for example if the value is a link or something.
An example:
{
/*
this is an explanation for something
*/
"linkToSomething": "https://something.net" // this is a link to something
}

There's also JSON5 which supports single and multi-line comments. Looks like the json5 package on pub.dev is what you're looking for. :)
Here's an example on how to use it:
import 'dart:io';
import 'package:json5/json5.dart';
void main(List<String> arguments) async {
// Read the file which contains the JSON.
final value = await File('<file>').readAsString();
// Parse it using the json5 package instead of dart:convert.
final parsed = json5Decode(value);
}

It's technically possible to remove comments using a RegExp, you just have to detect string literals too, to avoid triggering on comments inside strings, and then not remove the strings, only the comments. Strings are slightly tricky because of escapes, but at least JSON only uses one kind of quote.
var commentRE = RegExp(r'"(?:[^\\"]|\\[^])*"|/\*[^]*?\*/|//.*');
String removeComments(String jsonWithComments) =>
jsonWithComments.replaceAllMapped(commentRE, (m) {
var s = m[0]!;
return s.startsWith('"') ? s : "";
});
I'm assuming no nested comments because that makes detecting them non-regular.

Related

Ambiguous format output in nodejs

I am having output in following format as
"[{"a":"a1"},{"a":"a2"}]"
I want to actually extract it in array of json:
[
{
"a":"a1"
},
{
"a":"a2"
}
]
How to convert it?
You have tagged this with Node-RED - so my answer assumes that is the environment you are working in.
If you are passing a message to the Debug node and that is what you see in the Debug sidebar, that indicates your msg.payload is a String with the contents of [{"a":"a1"},{"a":"a2"}] - the Debug sidebar doesn't escape quotes when displaying strings like that.
So you likely already have exactly what you want - it just depends what you want to do with it next.
If you want to access the contents you need to parse it to a JavaScript Object. You can do this by passing your message through a JSON node.
Assuming your input contains the double quotes in the beginning and end, it is not possible to directly JSON.parse() the string.
In your case, you need to remove the first and last character (the double quotes) from your string before parsing it.
const unformattedString = '"[{"a":"a1"},{"a":"a2"}]"'
const formattedString = unformattedString.substr(1, unformattedString.length - 2)
const json = JSON.parse(formattedString)
The variable json now contains your JSON object.
I would suggest a different method which will get your work done without using any third party library.
var a = '[{"a":"a1"},{"a":"a2"}]';
var b = JSON.parse(a);
console.log(b); // b will return [{"a":"a1"},{"a":"a2"}]
Another way which is eval function which is generally not recommended
var d = eval(a);
If you want to use JQuery instead use :
var c = $.parseJSON(a);

Emoijis in JSON, Datapower

I have a mpgw where the request is JSON.
I save the content in a context variable with JSON.stringify(json)
The problem is when json contains a emoiji eg \uD83D\uDE0D tha variable no longer will be a string, it will be binary and the emoijis is shown as dots.
I need to use the the content of the variable later to calculate hmac so it has to look exact as the original json.
Is there any way to get around this?
Help wold be much appreciated.
We are running firmware: IDG.7.5.2.9
/Jocke D
Ok, from your comment I can conclude that it is the Stringify() that messes it up. This is according to the cookbook for escaping (there is a RFC describing this)...
Try adding your own function for stringify() that will handle unicode better:
function JSON_stringify(s, emit_unicode) {
var json = JSON.stringify(s);
return emit_unicode ? json : json.replace(/[\u007f-\uffff]/g,
function(c) {
return '\\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4);
}
);
}
ctx.setVar('json', JSON_stringify(json, false));
Something like that...

Manually parse json data according to kendo model

Any built-in ready-to-use solution in Kendo UI to parse JSON data according to schema.model?
Maybe something like kendo.parseData(json, model), which will return array of objects?
I was searching for something like that and couldn't find anything built-in. However, using Model.set apparently uses each field's parse logic, so I ended up writing this function which works pretty good:
function parse(model, json) {
// I initialize the model with the json data as a quick fix since
// setting the id field doesn't seem to work.
var parsed = new model(json);
var fields = Object.keys(model.fields);
for (var i=0; i<fields.length; i++) {
parsed.set(fields[i], json[fields[i]]);
}
return parsed;
}
Where model is the kendo.data.Model definition (or simply datasource.schema.model), and json is the raw object. Using or modifying it to accept and return arrays shouldn't be too hard, but for my use case I only needed a single object to be parsed at a time.
I actually saw your post the day you posted it but did not have the answer. I just needed to solve this problem myself as part of a refactoring. My solution is for DataSources, not for models directly.
kendo.data.DataSource.prototype.parse = function (data) {
return this.reader.data(data);
// Note that the original data will be modified. If that is not what you want, change to the following commented line
// return this.reader.data($.extend({}, data));
}
// ...
someGrid.dataSource.parse(myData);
If you want to do it directly with a model, you will need to look at the DataReader class in kendo.data.js and use a similar logic. Unfortunately, the DataReader takes a schema instead of a model and the part dealing with the model is not extracted in it's own method.

Replacing data fields with code in JSON.stringify?

So you can replace a property with a number, string, array, or object in JSON.stringify, like so:
var myObj = {
'allstar': aFunction;
}
function myReplacer(key, value) {
if(key === 'allstar') {
return 'newFunction()';
}
}
JSON.stringify(myObj, myReplacer); //returns '{"allstar": "newFunction()"}'
But can you change it so that it instead returns '{"allstar": newFunction()}' (without the quotes around newFunction)?
I assume typeof aFunction == "function"? If so, even JSON.stringify(myObj) will not do what you want it to do, but return '{}' i.e. an object without properties, because functions are not supported in JSON.
Your desired result is not even valid JSON. newFunction() without quotes is not a supported value (string, number, array, object, boolean, null).
Edit: you could try to return newfunction.toString() in your replacer, which should deliver your function's source as string. When converting the JSON back, you then must eval() this string to get the actual function.
#derpirscher provided a very good answer that will probably get more upvotes than this one, but this is my preferred answer:
Based on derpirscher's answer I decided it would be easier to make my own version of JSON.stringify that allows you to replace properties with your own source code, and changed the name of the module so that there is no naming conflict with JSON.
It's on my github account:
https://github.com/johnlarson/xerxes

How can I pass json string into HtmlHelper's result?

I want to pass a serialized json object and returned it within custom Html Helper's result. Something like this
public static HtmlString SomeHelper(this HTMLHelper htmlHelper)
{
var MyObject = new Foo();
var oSerializer = new JavaScriptSerializer();
var str = string.Format(#"<a href""#""
onclick=""var myObject = $.parseJSON(0);
alert('my object name property '+ myObject.Name); ""> Click me</a>",
oSerializer.Serialize(MyObject));
return new HtmlString(str);
}
That thing theoretically should work, but it doesn't. It puts serialized string to markup and then everything gets messy, because of double and single quotes. I tried to apply HtmlString after serialization, I even tried to use HTmlString.ToHtmlString(). Nothing works.
In fact I probably shouldn't do that. The click event call should be used unobtrusively. I know. Then I still have to save json object somewhere in the resulting markup.
Upd: I even tried to do that:
sJson.replace("\"",""")
Not helping. Browser automatically converts "s into ". I don't know how to preserve the markup
Is html.Encode the answer?
return new HtmlString(Html.Encode(str));
I guess the only solution would be to replace all double quotes in oSerializer.Serialize(MyObject)) with some other symbol, which wouldn't conflict in html markup, and then before the parsing put double quotes back, otherwise it wouldn't be a legit json string.