I have a string variable that is a string representation of an object. Like this:
{
"column": "'asdf'",
"sort": "true",
"search": "{\"asdf\":\"searchval\"}"
}
I would like to transform the above string into an object that looks like this:
{
column: 'asdf',
sort: 'true',
search: {
asdf: 'searchval'
}
}
I am planning on doing a search and replace regex expression for quotes and back slashes, and then using eval(), but that seems unsafe and innefficient. Is there an alternative method that would work better?
I am planning on assigning the object value of the string to an object variable.
Have you tried JSON.parse(); yet?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
var myOriginalData = JSON.stringify({"column": "'asdf'","sort": "true","search": "{\"asdf\":\"searchval\"}"});
myNewData = JSON.parse(myOriginalData, function (key, value) {
var type;
if (value && typeof value === 'object') {
type = value.type;
if (typeof type === 'string' && typeof window[type] === 'function') {
return new (window[type])(value);
}
}
return value;
});
console.log('myNewData -----------------------------------------------------------');
console.log(myNewData);
Working Example: http://plnkr.co/edit/2jLGIxx3AVEceVQsOpxL?p=preview
Immediately after posting this, I found out there is a JSON.parse(); function. The only reason I don't delete the question, is it might save someone time later.
All you need to do is pass the string variable as a parameter and it will output an object.
If anyone sees any problems with this solution, or knows a better solution, please make an answer!
Related
I have a variable that can either be a string or object like this:
value?: string | { name: string, type: string }
Trying something below but I get a compile error:
console.log(value?.name || value)
console.log(value?.type)
How can use this variable if it can be either type?
In this case you can do:
console.log(typeof value === 'string' ? value : value?.name)
Typescript can narrow the type using type-guards, see here for more details.
So you have two options
console.log(typeof value === 'string' ? value : value.name);
But as you used ?: in definition for this value (allowing undefined) and as i think that console is only for simple example there
if (value === undefined) {
} else if (typeof value === 'string') {
} else {
}
Would be best.
This issue you found is mostly done because both values for value variable are objects and ts saw that the types are not compatible and asks you to narrow them by hand
I know this seems like an odd problem, but at the moment I'm creating a webserver to save data to a mongodb database using mongoose. To use that, I need to create a model with a schema which basically defines the values I can search to, as well as the type they should be (String, Number, etc.)
As I said before, since it's a webserver, I'd like to make it so the webserver will create the model and the schema, with a body object in the request. However, there is an issue. I can only pass the type (String, Number, etc.) as a string. I've come up with a solution to parse the value into a type, that being the code below
getTypeByString: function (string) {
if (string == 'String') {
return String
}
if (string == 'Number') {
return Number
}
if (string == 'Array') {
return Array
}
if (string == 'Object') {
return Object
}
}
However, I feel like there is probably a more simple solution. If there is or isn't, please let me know! I'd like to release my code on GitHub eventually, and I'd like it to be as dynamic and simple as possible. Thank you in advance
String, Number, Array and Object are also properties of the global variable (or window variable if you are in a browser).
You can check it yourself by evaluating:
global['String'] === String // true
For this reason, you can just use the string to lookup the type within the global object, and return it:
getTypeByString: function (string) {
if (['String', 'Number', 'Array', 'Object'].includes(string)) // be sure that you are actually returning a type
return global[string];
return null;
In regards to getting a defined type from a string you can use an object to define the types and use the string as the key.
const DefinedTypes = {
String: String,
Number: Number,
Array: Array,
Object: Object,
CustomType: classOfCustomType
};
Using it.
const typeAsString = 'String';
const type = DefinedTypes[typeAsString];
You could use a switch statement to make the code a bit simpler:
getTypeByString: function(stype){
switch(stype){
case "String": return String;
case "Number": return Number;
case "Array": return Array;
case "Object" : return Object;
default: return null; // or throw an error
};
};
We have two potential values:
const value = `Hello World`;
and
const value = {message: 'Hello World'};
What I'm trying to do is a conditional where
if(is template literal) {
// Some code
} else {
// Some code
}
I've tried using
if(String.raw(value)){
} else {
}
But the object throws a type error. Does anyone have an easy reliable way to detect template literals in javascript?
Edit: Here is some further clarification for those who are asking.
const exampleFunc = (value) => {
// If I pass a string or template literal return as is
if (String.raw({raw: value})) return value;
const css = arr(styles).reduce((acc, obj) => {
// Passing an object handles a more complicated set of operations
}
}
Before I was using
if (String.raw(value)) return value;
And what was happening here is it was giving me a type error rather than handing me null. By passing {raw: value} to String.raw instead solved the problem and I can now detect whether its a string/template literal or an object.
The clarifications to why I'm doing it this way is a longer story that has to do with React & styled components.
There is no difference between using a string literal and a template literal (except, obviously, on the source code level).
But your first value is a string, while the second one is an object, and those are easy to distinguish:
if (typeof value == "string") {
console.log(value)
} else if (typeof value == "object" && typeof value.message == "string") {
console.log(value.message)
}
I have a an object jsonRes[0] containing values which need to be removed based on a condition. The following works to remove null, missing values and those equal to zero in the stringified object:
function replacer(key, value) {
// Filtering out properties
if (value === null || value === 0 || value === "") {
return undefined;
}
return value;
}
JSON.stringify(jsonRes[0], replacer, "\t")
However, when I add a condition using the the includes method, I receive an error:
function replacer(key, value) {
// Filtering out properties
if (value === null || value === 0 || value === "" || value.includes("$")) {
return undefined;
}
return value;
}
Uncaught TypeError: value.includes is not a function
Why is this the case and is there a workaround?
You can use String.indexOf() instead of String.includes, As it is available in ES6 and not supported in IE at all.
typeof value == "string" && value.indexOf('$') > -1
Also note if value is not string type it will still raise an error boolean, Number doesn't the the method. You can use typeof to validate whether value is a string.
The .includes() API is part of the String and Array data type.
So what the error is trying to tell you is that the value for variable value, e.g. an integer or object, does not have the property .includes.
You could do checks like
typeof a_string === 'string'
an_array instanceof Array
before the .includes() api to prevent this.
Obviously this will make your if statement rather ugly due to the number of checks you have.
Based on the way your code is written I suspect you are more interested in checking "String" than array. So becareful of arrays. Your code may not work properly if it is array.
Anyway here is a refractored version of your code.
function replacer(key, value) {
// Filtering out properties
if (!value || typeof value === "string" && value.includes("$")) {
return undefined;
}
return value;
}
console.log("NULL returns:" + replacer('test', null));
console.log("$Test returns:" + replacer('test', '$test'));
console.log("Blah returns:" + replacer('test', 'Blah'));
Just one more possibility: Maybe your value is not a string type object.
(typeof(value) == "string" && value.includes("$"))
I solved this error, which I was getting when applying "includes" to a "window.location" value, by appending ".toString();"
var requestUrl = window.location.toString();
if (requestUrl.includes(urlBase + "#")) {
...
I actually am not sure what type of the variable named value is, but anyway, Array.prototype.includes and String.prototype.includes are only available in ES6. You need to use babel-polyfill or any other bundling modules like rollup.js, webpack with babel or something like that to use includes function.
Instead of going JSON a json string and using $.parseJSON, I need to take my object and store it in a variable as string representing JSON.
(A library I'm dealing with expects a malformed JSON type so I need to mess around with it to get it to work.)
What's the best way to do this?
Edit: You should use the json2.js library from Douglas Crockford instead of implementing the code below. It provides some extra features and better/older browser support.
Grab the json2.js file from: https://github.com/douglascrockford/JSON-js
// implement JSON.stringify serialization
JSON.stringify = JSON.stringify || function (obj) {
var t = typeof (obj);
if (t != "object" || obj === null) {
// simple data type
if (t == "string") obj = '"'+obj+'"';
return String(obj);
}
else {
// recurse array or object
var n, v, json = [], arr = (obj && obj.constructor == Array);
for (n in obj) {
v = obj[n]; t = typeof(v);
if (t == "string") v = '"'+v+'"';
else if (t == "object" && v !== null) v = JSON.stringify(v);
json.push((arr ? "" : '"' + n + '":') + String(v));
}
return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
}
};
var tmp = {one: 1, two: "2"};
JSON.stringify(tmp); // '{"one":1,"two":"2"}'
Code from: http://www.sitepoint.com/blogs/2009/08/19/javascript-json-serialization/
I use
$.param(jsonObj)
which gets me the string.
Most browsers have a native JSON object these days, which includes parse and stringify methods. So just try JSON.stringify({}) and see if you get "{}". You can even pass in parameters to filter out keys or to do pretty-printing, e.g. JSON.stringify({a:1,b:2}, null, 2) puts a newline and 2 spaces in front of each key.
JSON.stringify({a:1,b:2}, null, 2)
gives
"{\n \"a\": 1,\n \"b\": 2\n}"
which prints as
{
"a": 1,
"b": 2
}
As for the messing around part of your question, use the second parameter. From http://www.javascriptkit.com/jsref/json.shtml :
The replacer parameter can either be a function or an array of
String/Numbers. It steps through each member within the JSON object to
let you decide what value each member should be changed to. As a
function it can return:
A number, string, or Boolean, which replaces the property's original value with the returned one.
An object, which is serialized then returned. Object methods or functions are not allowed, and are removed instead.
Null, which causes the property to be removed.
As an array, the values defined inside it corresponds to the names of
the properties inside the JSON object that should be retained when
converted into a JSON object.
The best way I have found is to use jQuery JSON
You could parse the JSON to an object, then create your malformed JSON from the ajavscript object. This may not be the best performance-wise, tho.
Otherwise, if you only need to make very small changes to the string, just treat it as a string, and mangle it using standard javascript.