Transform parts of JSON string output to boolean - javascript

Is there any way to convert some parts of JSON string to booleans ?
My JSON string example:
{
"file_id": {
"width": "560",
"height": "270",
"esc_button": "1",
"overlay_close": "1",
"overlay_opacity": "1"
}
}
If this was my personal project, I believe I would just convert the output of booleans into true/false strings and not 1 and 0, but since it isn't I wonder if there is a way to set what properties from JSON string are booleans. In this example booleans should be: esc_button, overlay_close but not overlay_opacity...
So since this is JavaScript project, I wonder what are my options and is there any easy way to do this ? There are more settings from this JSON string, I just posted part of it. Settings change depending on click event (different file_id === different settings)
EDIT:
Just figured I could use parseInt(settings[file_id].esc_button) to get boolean, but do I really have to use that all the time ? There might be other ways that I am not aware of.

JSON is just a data format. And if the data you are consuming chose to pass the string "0", you will get the string "0", and not false.
If "0" isn't what you want in your program you need to process the data a bit.
// for example
var processData = function(jsonString) {
var data = JSON.parse(jsonString);
data.esc_button = (data.esc_button == "1");
return data;
};
JSON.parse() itself doesn't provide a way to do this. It just decodes the data as it is in the source. If you need something different, you need to translate.
Ideally you should get your data source to give you this data in a better format. If it has real boolean literal values instead, you don't have to do any translation at all.
{
"file_id": {
"width": 560,
"height": 270,
"esc_button": true,
"overlay_close": false,
"overlay_opacity": 1
}
}
If your JSON looks like that, you just parse it and your done. By removing the quotes from width and height, those are now number values that require no translation to use in other math. And by reporting true or false for boolean values, those will get parsed as boolean literals, not strings. And it all just works.
This also resolves ambiguity. In your original JSON you had "1" for true and "1" for the opacity value, which I assume is expected to be a number form zero to one. Now you can look at the raw JSON data and see the difference.

JS is a dynamic language. You can do it yourself.
if (my_object[its_property]==="1")
my_object[its_property] = true
else
my_object[its_property] = false;
Or more tersely my_object=(my_object[its_property]==="1");.

Related

Remove object with given property from JSON using regex

Given I have a string which represents JSON object. It might be invalid, as there might be some params which will be replaced by another system (e.g. %param%). I need to remove all objects with known propertyName equal to "true" using regex.
{
"someTopLevelProp": "value",
"arrayOfData": [
{
"firstPropIAlwaysKnow": "value",
"dontCareProp": $paramValue$,
"dontCareProp2": 2,
"flagWhichShouldIUse": true,
"somethingAtTheEnd": "value"
},
{
"absolutelyAnotherObject": %paramValue%
},
{
"firstPropIAlwaysKnow": "value",
"dontCareProp": "value",
"dontCareProp2": 2,
"flagWhichShouldIUse": false,
"somethingAtTheEnd": "value"
},
{
"firstPropIAlwaysKnow": "value",
"dontCareProp": "value",
"dontCareProp2": 2,
"flagWhichShouldIUse": true,
"somethingAtTheEnd": "value"
}
]
}
In the example above, I always have "firstPropIAlwaysKnow" which means that object can contain flag which I need. After that there might be other properties. But the most important here is "flagWhichShouldIUse" prop, which mean this object should be removed (but only in case when value equal to 'true'). As result I should receive:
{
"someTopLevelProp": "value",
"arrayOfData": [
{
"absolutelyAnotherObject": %paramValue%
},
{
"firstPropIAlwaysKnow": "value",
"dontCareProp": "value",
"dontCareProp2": 2,
"flagWhichShouldIUse": false,
"somethingAtTheEnd": "value"
}
]
}
My knowledge in regex are not strong enough, thus kindly ask for community's help.
P.S. Please do not mention that parsing JSON with regex it's crazy\incorrect\bad idea - be sure I know that.
ANSWER: now I have working regex which do that stuff. Thank you everyone who tried to help here. Maybe it will be useful for someone.
/{\s+?"firstPropIAlwaysKnow": "value"[^{}]+?(?:\{[^}]*\}[^}]+?)*[^}]+?"flagWhichShouldIUse": true[^}]+?},?/gi
Regexper
You really can't do this with just regular expressions. Something like this might work:
let filtered = jsonstring
// split into the individual 'objects'
// might need to modify this depending on formatting. You
// could use something like /},\s*{/ to split the string,
// but couldn't re-join with same formatting
.split('},{')
// filter for only the strings with the relevant property
// set to false
.filter(s => s.match(/"flagWhichShouldIUse":\s*false/) // again, may need to change
// put humpty-dumpty back together again
.join('},{');
The exact splitting method will depend heavily on the structure of your JSON, and this isn't fool-proof. It doesn't handle nesting properly. If your JSON is pretty-printed, you could use the number of tab/space characters as part of the splitter: this for instance would only split for one tab only: /\n\t},\s*{/

JSON.stringify and JSON.parse get different result

I have an Object I use JSON.stringify to create JSON string.
Than I save that string into file.
Then I read that file. Make JSON.parse and try to use that object again.
But it does not work anymore.
For example if I use [i] to select element it doesnt select element but just take charset like its a string :(
Can any body help with that?
This is some kind of example but actuall JSON is toooo long:
{"featureCollection":
{"layers":"[
{\"layerDefinition\":
{\"currentVersion\": 10.3,
\"id\": 0,
\"supportsCoordinatesQuantization\": true,
\"advancedQueryCapabilities\":
{
\"supportsPagination\": true,
\"supportsDistinct\": true
},
\"geometryType\":
\"esriGeometryPolygon\", \"minScale\": 0,
\"maxScale\": 0,
\"extent\":
{},
\"drawingInfo\":
{\"renderer\":
{\"type\": \"simple\", \"symbol\":
{\"type\": \"esriSFS\", \"style\": \"esriSFSSolid\", \"color\": [76, 129, 205, 191], \"outline\":
{\"type\": \"esriSLS\", \"style\": \"esriSLSSolid\", \"color\": [0, 0, 0, 255], \"width\": 0.75}
}
},
What's going on is that the layers property of the featureCollection property is not an array, it's a JSON encoding of an array. You need to decode it again to process the contents. Assuming json_obj is the full object, you need to do:
var layers = JSON.parse(json_obj.featureCollection.layers);
Then you can access layers[i].layerDefinition.currentDefinition.
I don't know why it's done that way -- you may want to fix the code that creates the JSON in the first place, and remove the part that calls JSON.stringify() when storing into the layers property.
It looks as though the process that is writing the JSON string to a file is escaping the quotes which is causing the issues when you try to parse. You either need to stop the process from escaping the quotes, or use replace to strip out the escaped quotes of your JSON string prior to passing it to parse

$.inArray is giving -1?

This should be pretty straight forward:
HTML
my link
<input type="hidden" id="pageids" value="28,27,26,17,18,19,">
Jquery
var thumbaid = $('#thumba').data("id");
// get position
var itemids = $('#pageids').val();
var itemids_array = itemids.split(',');
var currentpos = $.inArray(thumbaid, itemids_array );
alert(currentpos);
Gives me -1?
The funny thing is that if I replace " $(thumba).data("id")" for a number in the jquery code as "26", it works!
The result should be, in this case, "2".
Any ideas?
You need to convert the value to a string.
var thumbaid = $('#thumba').data("id").toString();
Why...? If you were to
console.log(itemids_array);
you would see this
["28", "27", "26", "17", "18", "19", ""]
They are not numbers, they are strings. See http://api.jquery.com/data/
That is because the thumbaid is a number, and the itemids_array contains strings. Try var currentpos = $.inArray(thumbaid.toString(), itemids_array );
jQuery's data function reads the data- attributes and parses digits to numbers.
jQuery's data function does things to the data it reads from the data-* attributes on initialization, including turning number-like strings into numbers. Since $.inArray does an === check, that's why it fails. You end up looking for the number 26 in an array of strings.
If you simply use .attr("data-id") instead, the conversion won't happen.
This behavior is documented in the data docs:
Every attempt is made to convert the string to a JavaScript value (this includes booleans, numbers, objects, arrays, and null). A value is only converted to a number if doing so doesn't change the value's representation. For example, "1E02" and "100.000" are equivalent as numbers (numeric value 100) but converting them would alter their representation so they are left as strings. The string value "100" is converted to the number 100.
If you're only using data to read data-* attributes, I recommend using attr instead to avoid this kind of thing, and to avoid the confusion caused by the fact that while data initializes from data-* attributes, it doesn't write to them when you set data. Of course, if you need to store data associated with elements and you don't want it on an attribute (because it's not string data, or you don't want it showing in the DOM inspector), data is the right tool for that job.
The reason its not working, is because jQuery data is returning an int not string.
See this example.
my link
<input type="hidden" id="pageids" value="28,27,26,17,18,19,">
Javascript:
var thumbaid = $('#thumba').data('id').toString();
// get position
var itemids = $('#pageids').val();
var itemids_array = itemids.split(',');
console.log(itemids_array);
var currentpos = $.inArray(thumbaid, itemids_array );
console.log(currentpos);
$().data() will convert the data-* attribute's value to a JavaScript value. In your case, thumbaid is converted to a number.
$.inArray compares elements using the strict equality operator(===). That is, '26' === 26 returns false as no type coercion occurs.
From the jQuery.data() docs:
Every attempt is made to convert the string to a JavaScript value
(this includes booleans, numbers, objects, arrays, and null). A value
is only converted to a number if doing so doesn't change the value's
representation. For example, "1E02" and "100.000" are equivalent as
numbers (numeric value 100) but converting them would alter their
representation so they are left as strings. The string value "100" is
converted to the number 100.

JSON with empty numeral value? (not 0)

Given a JSON such:
[
{ "id":"A", "status": 1, "rank":1, "score": },
{ "id":"B", "status": 1, "rank":1, "score": }
]
My script fails due to the empty score.
Given a JS such :
if (json[i].score) { do something } else { calculate it }
I want to keep the field empty, and not use 0. I may use "score": "", but this will imply that it's a string (empty at start), while I want score to be a numeral (empty at start). So the number I push in it stay a number, and not a string.
How to state an empty/undefined numeral ?
Note: I intuitively think it's why I sometime meet undefined.
EDIT: the question was edited to clarify the context, the need to check the existence of obj.score, where 0 would be misleading.
TL;DR: Use 0 (zero), if everyone starts with zero score. Use null, if you specifically want to say that someone's score is not set yet. Do not define the property, if it should not be placed in specific case (like object that should not even have "score" property).
Omitting the value in JSON object
Well, in JSON you are not allowed to just omit the value. It must be set to something like number (integer or float), object, list, boolean, null or string. To read more about syntax, try this resource: http://json.org/. This is the diagram taken from that site, showing you the syntax of object representations in JSON:
Most popular approaches: null, 0 (zero), undefined
The usual approach is to set null. In other cases it can be better to use 0 (zero), if applicable (eg. the field means "sum").
Another approach is just to not set the property. After deserialization you are then able to perform tests checking the existence of specific property like that:
JavaScript:
if (typeof my_object.score !== 'undefined'){
// "score" key exists in the object
}
Python:
if 'score' in my_object:
pass # "score" key exists in the object
PHP:
if (array_key_exists('score', $my_object)) {
// "score" key exists in the object
}
Less consistent approaches: false, ""
Some people also accept the value to be false in such case, but it is rather inconsistent. Similarly when it comes to empty string (""). However, both cases should be properly supported in most programming languages during deserialization.
Why not just start score at 0? Everyone will start with a score of 0 in just about anything involving score.
[
{ "id":"A", "status": 1, "rank":1, "score": 0 },
{ "id":"B", "status": 1, "rank":1, "score": 0 }
]
By definition, a numeral value is a value type, which cannot be null. Only reference types (like strings, arrays, etc.) should be initialized to null.
For the semantic of your situation, I would suggest you to use a boolean to know if weither or not there is a score to be read.
[
{ "id":"A", "status": 1, "rank":1, "empty":true },
{ "id":"B", "status": 1, "rank":1, "empty":false, "score":100}
]
Then,
if (!foo.empty) {
var score = foo.score;
}
While a null could be tested as well, it is a wrong representation of a number.

JSON Data format

Not very familiar with JSON data and how to create it using JavaScript.this is what i am trying
i have created two JS variables
var json={};
var json1={};
i have some certain loops to iterate data and loops like
for(firstLoop){
key=outerKey;
for(innerLook){
innerKey=innerkey;
for(lastloop){
jsonValues= create values in a java variable
}
json[innerKey]=jsonValues;
}
json1[outerKey]=JSON.stringify(json);
}
Doing this i am getting following output
Required: "{"Center":"radio_Required_Center_0,radio_Required_Center_1,","Left":"radio_Required_Left_0,"}"
which is not a valid JSON format.My idea id to create a outer-key say Required and than an inner one's in my case Center and Left
so that i can iterate each value with respect to key Center (i can break the string based on ')
i am not sure how to create correct structure and i don't want to do it on server side which can be done easily.
any solution or hint will really be helpful.
Edit
var data= JSON.stringify(json1);
giving following output
{"Required":"{\"Center\":\"radio_Required_Center_0,radio_Required_Center_1,\",\"Left\":\"radio_Required_Left_0,\"}"}
which is valid JSON data, now i need to execute some code based on the data in the JSON and here are my requirements
Fetch the outer-key (Required or there can be other also).
Fetch all values under the key Center and Left
Create array from the value retrieved from step 2 (split based on ",").
Loop through the values obtained from step 3 and execute the logic.
My real challenge is at step number 2 and 3 where i need to fetch the keys and its associated values and those key and not predefined so i can not access them based on there name.
I am thinking of a way to get key and its values without hard coding key names and execute my logic.
is it possible in by this approach or not?
If you're using a modern version of Javascript, it comes with JSON functions built-in.
var jsonString = JSON.stringify(jsobject);
...to convert a JS object into a JSON string.
(See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringify)
and
var jsOject = JSON.parse(jsomString);
...to convert back in the other direction.
(see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/parse)
The only time you need to worry about this not being built-in is if you're using an old browser - for example, older versions of IE. However, in this case, there are polyfill libraries like this one that you can load which will implement the above syntax for you.
If you're just trying to compose one big JSON object, you don't need to stringify one JSON object before adding it to another... So instead of doing JSON.stringify(json) you can just do json1[outerKey]=json
for(firstLoop){
key=outerKey;
for(innerLook){
innerKey=innerkey;
for(lastloop){
jsonValues= create values in a java variable
}
json[innerKey]=jsonValues;
}
json1[outerKey]=json;
}
try jsonlint.com to validate your JSON
This is valid:
{
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
This is valid too:
{
"Required": {
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
}
This isn't:
Required: {
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
using JSON.stringify() is the right way of converting javascript objects to JSON string format. However if you want to put it in a variable you should do that first, later in the last step you convert to JSON string.
var output = { "Required": yourpreviousjsonvar },
jsonString = JSON.strinify(output);
EDIT:
You need to process the data first you probably won't even need the JSON string if I understand you right. (=> if however you already got a string you need it parsed first. Do it using JSON.parse(yourjsonstring))
Fetch the outer-key (Required or there can be other also).
Fetch all values under the key Center and Left
Create array from the value retrieved from step 2 (split based on ",").
Loop through the values obtained from step 3 and execute the logic.
having this as variable:
var a = {
"Required": {
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
}
// step 1
console.log(a.Required);
// step 2
console.log(a.Required.Center);
console.log(a.Required.Left);
// step 3
var center = a.Required.Center.split(',');
var left = a.Required.Left.split(',');
// step 4
for(var i = 0; i<center.length; i++){
console.log("doing somthing with", center[i]);
}
Here is a fiddle => use Chrome/safari/Opera's developpertools and check the console to check the output. Or use firebug (in firefox) Or IE9 or greater (F12).
Use native Javascript toSource :
var obj= new Object();
var obj1= new Object();
for(firstLoop){
key=outerKey;
for(innerLook){
innerKey=innerkey;
for(lastloop){
jsonValues= create values in a java variable
}
obj.innerKey=jsonValues;
}
obj1.outerKey=obj;
}
json = obj.toSource();
json1 = obj1.toSource();

Categories