ES6 Set does not serialize to array - json

I've noticed that the Set in ES2015 does not implement a simple toJSON function, such as serializing to an array. Below is the implementation I came up with that does just that:
Object.defineProperty(Set.prototype, 'toJSON', {
enumerable: false,
value: function () {
return [...this];
}
});
Is there any reason why a Set does not serialize to an array?
Are there any edge cases where this override for toJSON is a bad idea?

See this answer as to why there can't be a general toJSON case for Maps, and for similar reasons, Sets. Basically, keys and/or Set items can be anything, including objects and references to other things that can't be serialized into JSON (which, remember, is a specific format with specific, stricter rules than just "turn into intelligible data of another type"). What you want here is more like "toArray" anyhow. You method already works for that inline, as would Array.from(Set), I think.
But if you wanted to add this sort of method to the prototype for your own internal usage without risking possible problems if a similar (but not identical) method is ever added, you could use a Symbol key'd prop.
var toArray = Symbol('toArray');
Object.defineProperty(Set.prototype, toArray, {
enumerable: false,
value: function () {
return [...this];
}
});
var g = new Set();
g.add(9);
g[toArray]();//-> [9]
If you do that, then you are guaranteed to not cause problems with anything other than your own code, since only your code will have access to the toArray Symbol key that references that method.

Related

Converting circular structure to JSON at JSON.stringify ()

I am having an issue while cloning objects. I have strategies array to which i am trying to add strategy objects.It works some times while errors with the following error message. Could somebody tell me what the problem could be.
The strategy object consists of objects of objects. In the Add method , I am trying to add Strategy of element zero to the strategy array.
export interface Strategy {
domicile: Domicile;
captiveAssumption: StrategyCaptiveAssumption;
modelingAssumptions: StrategyModelingAssumption;
selectedLinesOfBusiness: SelectedLineOfBusinessInput[];
accountRules: StrategySpecialAccountRules;
minCapitalContribution: StrategyMinCapitalContribution;
results: Results;
}
Converting circular structure to JSON
at JSON.stringify ()
add() {
if (!this.showAddStrategy) {
return;
}
const strategy: Strategy = JSON.parse(JSON.stringify(this.strategies[0]));
this.strategies.push(this.strategies[0]);
this.save.emit();
this._expandLastStrategy();
}
A circular structure is a structure which references itself as a value. JSON.stringify does not support such structures, since it would result in an infinitely-long string.
What you need is a deep cloning function which does not use JSON.stringify. Such implementation can be found here.

Faster way to get class instance from Ajax

I have this simple function to retrive data from database:
function find_object() {
$.ajax({type: 'POST',
url: '/find-object/',
data: {
position: position,
},
success: function (result_list) {
if (result_list.result === 'OK') {
console.log(result_list.data.myobject)
} else {
console.log('not found')
};
}
});
};
and here the view:
def find_object(request):
if request.is_ajax():
position = request.POST.get('position', None);
try:
my_object=My_Class.objects.get(coordinate=position)
except:
return JsonResponse({'result': 'None'})
my_other_object=My_Other_Class.objects.filter(my_ForeignKey_field=my_object)
if my_related_object:
my_field=my_other_object.my_field
#do things
return JsonResponse({'result': 'OK', 'data': { 'myobject': my_object }})
It gives error because my_object is not JSON serializable, but it isn't a queryset because it comes from .get() so I can't serialize like this:
my_object_json=serializers.serialize('json', my_object)
In the first request I'm using .get() because it's faster than .filter() (when the exception are rare, and they are). For each position there is only one my_object or (rarely) none. In the second request I'm using .filter() because the exceptions aren't rare.
So the questions:
1) is it faster to use .filter() instead .get() and then serialize my_object like above or there is some other way? Maybe a no-JsonResponse? I need the object with all the fields
2) my_other_object is an instance of a class where my_object is ForeignKey. What I want? If my_object exist I want look if exist a corrispondent my_other_object and find the value of one of his fields. For each my_object there is only one my_other_object or none. My solution works but maybe there is a faster way to do so.
Also: should I use a else condition on if request.is_ajax()? Why shouldn't be ajax?
thank you
0) Django model instances aren't serializable. You can't serialize a queryset either, but it doesn't mean you could serialize an instance. A simple way to make it serializable is to get its values like this
my_object_serialized = list(my_object.values('the', 'fields', 'that', 'you', 'need'))
1) This requires a bit longer answer. There is a performance difference between just get() and filter() since get() can return the first instance it sees in the database, but filter() has to traverse the whole table. But the second where you change filter() to filter()[0] it should be equal to get() performance-wise. AND this is all pretty much irrelevant. Why?
filter() and get() exist separately because they are meant to be used differently from one another. If you KNOW that you only have one such object in the database or you want to verify that you only have a single object, then you use get(), because it raises an exception when there are 0 or more instances of the queried thing. You can even do MyModel.objects.filter(myfield=myvalue).get() for the very same reason - get() verifies that there's only one object.
If you just want to get the first one and you don't care how many there are, then the preferred way is to use filter().first() pattern that will either return the first object or None in case there are none. And just as with getting the first item with [0] notation, calling first() on a filter() has exactly the same performance as calling get(), the difference is rather what happens on Python side.
2) Your solution is pretty much fine. For this use case, it's okay.
Bonus question: If the view is only meant to be used via ajax, I would add return HttpResponseBadRequest() at the end either in an else or just on base function level.

Immutable JS duplicate / copy List within Map

I have an Immutable Map like this
Immutable.fromJS({
sortingOnFields: false,
items: [],
selectedItems: [],
columnsConfigs: {
meta: {},
columns: {}
},
});
how do I copy the items List to selectedItems list.
This return state.set('selectedItems', state.get('items'));
doesn't do the job correctly as later if I do
props.listing.get('selectedItems').includes(Immutable.fromJS(item));
where Immutable.fromJS(item) is from the 'items' List, it returns false.
I tried this which works but looks a bit too much
return state.set('selectedItems', Immutable.fromJS(state.get('items').toJS()));
any ideas of a better solution?
The problem is with your test. You are successfully setting the same List at both keys. You're retrieving the value at items, which is a List, and you're setting that exact same List as the value at selectedItems.
Even though that is working, your test isn't doing its job. You wrote:
props.listing.get('selectedItems').includes(Immutable.fromJS(item));
That line says: Get the List at selectedItems. Now create a brand new Immutable object using the fromJS method. Does the List at selectedItems contain that new Immutable object? The answer is no, because you just created that item from scratch, so it is definitely not contained in the List at selectedItems.
If each item is a primitive value, you can just check like this:
props.listing.get('selectedItems').includes(item);
If each item is a object, then did you convert it to an Immutable object? If not, then you can pass in a reference to the item, as above. If you did convert it to an Immutable object, make sure you pass a reference to the correct Immutable equivalent to the includes method.

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.

Is there a way to "grep" for a keyword in a JavaScript object in Chrome Dev Tools?

I often work with large JavaScript objects and instead of manually opening and closing "branches", I would like to simply search for a particular string and show any key or value that matches.
Sort of like "grepping" for a keyword in a JavaScript object. Is this possible (especially in Chrome Dev Tool)?
Unfortunately I was hoping I could at least try the JSON.stringify() trick and then search on the raw JSON in a text editor, but I get the following error:
Uncaught TypeError: Converting circular structure to JSON
You can look at the object's keys and match against them:
function grepKeys(o, query){
var ret = {};
Object.keys(o).filter(function(key){
return key.includes(query);
}).forEach(function(key){ // can reduce instead
ret[key] = o[key]; // copy over
});
return ret;
}
Which'd let you return a partial object with all the keys that contain the string you specified. Note that this will not show any prototype keys but can be easily extended to allow it (by using a for... in instead of an Object.keys or by using recursion):
var o = grepKeys({buzz:5, fuzz:3, foo:4}, "zz");
o; // Object {buzz: 5, fuzz: 3}