Consider the following TypeScript class:
export class Spot {
public flight:number;
public dateAndTimes:Map<string,string>
public unitCost:number;
constructor(){
this.flight=0;
this.dateAndTimes= new Map<string,string>();
this.unitCost=0;
}
}
How can I convert the Spot object to JSON?
I try JSON.stringify(spot), but the attribute dateAndTimes it's serialized as empty... for example:
"spot": {
'flight':2,
{},
'unitCost':3500
}
Thank you very much!
Quoting from the MDN documentation for JSON.stringify:
All the other Object instances (including Map, Set, WeakMap, and WeakSet) will have only their enumerable properties serialized.
As a Map can have any type for keys and values then even if you were able to stringify it the JSON spec does not account for any types outside of "objects, arrays, numbers, strings, booleans, and null". Therefore if any of the keys or values of the Map are not of those types then it would not be allowed by the specification.
That last point is extremely important as even if a Map was somehow serialized to JSON but included any type of key or value not of the aforementioned allowed types then it is not determinable how a parser would process the resultant JSON back into an object. If it is not necessary to use a Map then I would recommend using a plain object for this to avoid this issue completely.
Note that it is also not possible to roll your own replacer function for the JSON.stringify method to handle that functionality.
Related
I have a React component state that holds many different classes that needs to be stringify()'d. Most of the components need to be specially treated before they can be put into the JSON object. I believe that using the replacer() and if statements to check the type and then modify the output would be too cumbersome. Short of creating a custom parsing system, is there a way to customize the stringify() in what it parses?
The idea would be to have a custom function (toString() for example) in each class that when the parser reaches the class, instead of going through the key-value pairs, would call the function and append it to the JSON object.
From JSON.stringify description
If the value has a toJSON() method, it's responsible to define what data will be serialized.
Usage
JSON.stringify({ toJSON() {return {a: 'eureka'}}})
I am trying to return the value under the key 'str' in an Object but I am having trouble accessing the value.
This is what is returned in the console:
Currently I am using a map function to go over the array and just return the _str value like so:
let idx = currentArray.map(function(x) {
return x._id._str;
});
However it is still returning the value as an object. How can I get just the value of the _str key?
Here is the full array without specifying the id field. This is what is returned if you jsut return 'x' in the map function.
You've clarified that the screenshot is of x._id. So to access _str, you'd use x._id[0]._str: The _str property is in the object referenced by the 0 property (the first entry in the array x._id refers to).
Note that in general, _-prefixed properties are meant not to be accessed by code outside the code responsible for the objects in question. You don't seem to be responsible for them, so accessing those properties is likely to make your code rely on undocumented properties that may change in the next "dot" release of whatever lib you're using. It's just convention, but it's a very common convention.
If you right click on the property, most browser consoles offer the ability to copy property path.
Based on this SO post and the docs, it appears that you can probably use x._id.str.
If I understand correctly, you are receiving the str value but it is an object instead of the string literal. In other words, you are getting _str: "598..." instead of "598....". A possible solution would be to use the mongo javascript function to convert the str value to a string.
In your case, I think something like return x._id.str; may work as _id is a MongoID.ObjectID.
I've also linked the documentation below for reference.
https://docs.mongodb.com/manual/reference/method/ObjectId/
Here's a relevant SO answer as well: Convert ObjectID (Mongodb) to String in JavaScript
I think you should write x[_id]._str because _id is one of the array objects.
I have written a NPAPI Plugin using firebreath framework. I am able to pass simple numeric values from Javascript and access them in my (C++)plugin, perform operations and then return the result. I would like to know how to operate on vectors now i.e arrays. I do not want to allocate new array inside my plugin and copy the array from JavaScript(Although I have no clue on how to do it). How can I directly access the JavaScript array in my plugin ? Is there a special way to do it ?
From the Firebreath website:
Javascript objects can be used with the FB::JSObjectPtr type. Examples of JavaScript objects that you may want to use include:
Javascript objects (with methods and/or value members)
Javascript Arrays (that you plan to modify; otherwise you can use a container type)
Javascript methods for callback
Arrays are objects; get values with getProperty(n) or getProperty("length") etc
You can also use methods like ->invoke("push", FB::variant_list_of(val)) etc
(on the JSAPI method in order to use the JSObjectPtr type you should use a method that looks something like:)
void doSomethingWithAnArray(const FB::JSObjectPtr& array) { ... }
Also remember that FireBreath can't tell what type of js object it is, just that there is a js object; you'll have to do your own error detection for the case where they don't give you an actual array but some other object instead.
I want certain properties to be serialized as 'objects' and not strings. E.g.
{"onClickHandler": OnClickHandler,
"onMouseOut": OnMouseOutHandler}
The class def is like this:
public class handlers {
public string OnClickHandler;
public string OnMouseOutHandler;
}
Currently it comes out as:
handlers: {"onClickHandler": "OnClickHandler",
"onMouseOut": "OnMouseOutHandler"}
As you can guess, these are client side event handlers and correspond to javascript functions defined elsewhere. By emitting them within quotes, they are not interpreted as functions but as literal strings.
Edit:
Taking a cue out of Dave's answer, figured out a way:
first a little bit of scrubbing:
for (var handler in this.handlers) {
if(window[this.handlers[handler]])
this.handlers[handler] = window[this.handlers[handler]];
};
and then call jQuery bind normally
$elem.bind(this.handlers);
Accepting Dave's answer as that is closest.
JSON does not support representing functions. JSON consists of arrays of values, and objects (containing variables). Values in JSON can only be strings, numbers, objects or arrays (see the linked page for nice grammar diagram).
What you're after is javascript code, not a JSON object. If you're wanting to emit a reference to a function defined elsewhere, you may have to (shudder) use eval to execute it.
As someone else mentioned, that wouldn't be valid JSON anyway (which precludes you from using JSON.parse(), among other potential drawbacks).
If your event handler functions are defined in the global window scope, you could call them like this:
// This is equivalent to defining window.clickEventHandler or
// window['clickEventHandler'] as a function variable.
function clickEventHander() {
// Magic.
}
// Valid JSON, using strings to reference the handler's name.
var json = '{"onClickHandler": "clickEventHandler"}'
// You might be using eval() or a framework for this currently.
var handlerMappings = JSON.parse(json);
window[handlerMappings.onClickHandler]();
Does anyone know of decent examples of custom JavaScriptConverter classes? The MSDN's only example is of one converting a ListItemCollection. What about custom classes? What if the custom class has a property of another custom class? Do we need two converters? Any references would be greatly appreciated.
Thanks!
You should only need one converter. The example basically outlines how to use the JavaScript converter for any custom class. It doesn't need to be a class that is part of the framework.
It will also work for any properties of a custom class that are themselves a custom class.
JSON views objects as collections of key/value pairs, so the documentation example shows how you should take any properties of your object and put them into Dictionaries (a type of Key/Value pair object). If you need a nested custom type, you can just nest Key/Value pairs inside of your main Key/Value pair collection.
Also, unless you have very specific needs (built-in serialization either won't work, or doesn't output what you want), you should just use the JavaScriptSerializer class.
JavaScriptSerializer serializer = new JavaScriptSerializer();
MyCustomObject obj = new MyCustomObject();
string json = serializer.Serialize(obj);
MyCustomObject object2 = serializer.Deserialize<MyCustomObject>(json);
That should do what you want in 95% of cases.