I have a JSON string and want to convert it to a an object in javascript, the only issue is the destination object will have different variable names and i want key to assign to a variable and value to a different variable
The JSON would be
{
"Value1":"Type1",
"Value2":"Type2"
}
The object will be
interface Object {
Value: string;
Type: string;
}
I want the JSON to be converted to object array where assigning key (Value1/Value2) to object variable Value and value (Type1/Type2) to object variable Type so the resultant object array would look like below
[{Value: Value1, Type: Type1}, {Value: Value2, Type: Type2}]
Regular JSON.parse wouldn't work as the object is different from json string, any help is appreciated.
You can make use of Object.entries and map:
const obj = {
"Value1":"Type1",
"Value2":"Type2"
};
const result = Object.entries(obj).map(([Value, Type])=>({Value, Type}));
console.log(result);
You can use this:
Object.entries(JSON.parse(json)).map(([Value, Type]) => {
return { Value, Type };
});
Refular JSON.parse works just fine, you just need to do a conversion step after parsing. Break the problem down in multiple steps.
type MyInput = {
Value1: string;
Value2: string;
}
type MyOutput = {
Value: string;
Type: string;
}
function myConversionFunction(input: MyInput): MyOutput {
return {
Value: input.Value1,
Type: input.Value2
}
}
const out = JSON.parse(str).map(myConversionFunction);
This is a great question that I often run into in other languages.
I find it easiest to create a helper function or constructor that maps the appropriate key to the appropriate variables. You take the keys in as parameters and create the object assigning each key to the correct variable.
You will always be mapping the same key name to the same variable name so if you set this mapping once in this helper method and call it for each object it should work correctly for each of them.
I don't actively code in JS. Maybe you thought of this and a reason it doesn't work well?
Related
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
};
};
I have a todo object
from example, this is my expected object
foo ={
name:'F',
lastName: 'JOI',
address:{
street:'where?'
}
}
and I got all these fields with more properties that I want to remove
for example, this is the object that I receive
bar ={
name:'F',
lastName: 'JOI',
address:{
street:'where?'
},
more:'temp',
prop:'should remove'
}
Does there is a way to remove the unnecessary without loop foreach property?
I am using TypeScript if it can help
The simplest thing is to write the code for it directly:
const foo: YourType = {
bar.name,
bar.lastName,
bar.address,
bar.street
};
// Use `foo`
That also has the advantage of being typesafe in TypeScript; if you tried to grab a property that isn't a member of YourType or that doesn't exist on bar, you'll get an error from TypeScript.
No.
TypeScript checks that types matches but it does not provide any utility to iterate over type properties, because all the type annotations disappear at compile time.
If you want to delete several keys, this information will have to be present on the "JS layer", because the "TS layer" (types, interfaces, etc) get compiled out, so you'll have to have somewhere a plain JS object or array with all the keys to delete (or to keep). Possible implementations:
// keep only the keys you want
const bar = {
name: bar.name,
lastName: bar.lastName,
address: bar.address,
}
// same but with a helper
const keepProps = (src, keys) => Object
.entries(src)
.reduce(
(dst, [key, value]) => {
if (keys.includes(key)) dst[key] = value;
return dst;
},
{}
);
const bar = keepProps(foo, ['name', 'lastName', 'address']);
// remove unwanted keys
const bar = { ...foo }; // spread is required to create a different object reference
delete bar.more;
delete bar.prop;
About that "no for loop" requirement, it won't be possible, if you want to do several times the same operation, it will either be an explicit loop, or loop hidden by the syntax, like { ...obj } or Array.filter.
I'm a programming beginner.
API post call accepts object variable (derived from variable) as a string as follows
"option":
{
"235": “30”
},
{
"238": “32”
}
My code angular 6
option = [];
---
this.option.push({
[option.product_option_id]: $event
});
which result
option = [ {
235: 30
}]
but need this variable in double-quoted "235".
please help
but need this variable in double-quoted "235"
By which you mean that you need it to be a string.
Don't worry, it is. When you use a number as a property name, it's converted to a string automatically. Property names can only be strings or Symbols, so things that aren't strings or Symbols get converted to string:
class Example {
constructor() {
this.option = [];
const option = {
product_option_id: 42
};
const $event = {};
this.option.push({
[option.product_option_id]: $event
});
const pushed = this.option[0];
for (const key of Object.keys(pushed)) {
console.log(`${key}: ${typeof key}`);
}
}
}
new Example();
That said, the expression within the [] of a computed property name is just that: an expression. So if you wanted to be explicit, you could use String there:
option.push({
[String(option.product_option_id)]: $event
});
I want to check if an object already exists in a given object by only having the object.
For instance:
const information = {
...
city: {
Streetname: ''
}
}
Now, I get the city object and want to check if it is already in the information object (without knowing the property name). The city could be n deep in the information object.
To get the property name of an object you can use Object.keys(). The first problem solved.
Now we need to iterate through the whole object including nested objects. This is the second problem.
And compare it to a query object. This is the third problem.
I assume that we have an object that only contains "simple" though nested objects with primitive values (I do not consider objects with functions or arrays)
// let's assume we have this object
const information = {
city: {
Streetname: 'streetname1'
},
house: {
color: "blue",
height: 100,
city: {
findMe: { Streetname: '' } // we want to get the path to this property 'findMe'
}
},
findMeToo: {
Streetname: '' // we also want to get the path to this proeprty 'findMeToo'
},
willNotFindMe: {
streetname: '' // case sensetive
}
}
// this is our object we want to use to find the property name with
const queryObject = {
Streetname : ''
}
If you use === to compare Objects you will always compare by reference. In our case, we are interested to compare the values. There is a rather extensive checking involved if you want to do it for more complex objects (read this SO comment for details), we will use a simplistic version:
// Note that this only evaluates to true if EVERYTHING is equal.
// This includes the order of the properties, since we are eventually comparing strings here.
JSON.stringify(obj1) === JSON.stringify(obj2)
Before we start to implement our property pathfinder I will introduce a simple function to check if a given value is an Object or a primitive value.
function isObject(obj) {
return obj === Object(obj); // if you pass a string it will create an object and compare it to a string and thus result to false
}
We use this function to know when to stop diving deeper since we reached a primitive value which does not contain any further objects. We loop through the whole object and dive deeper every time we find a nested object.
function findPropertyPath(obj, currentPropertyPath) {
const keys = isObject(obj) ? Object.keys(obj) : []; // if it is not an Object we want to assign an empty array or Object.keys() will implicitly cast a String to an array object
const previousPath = currentPropertyPath; // set to the parent node
keys.forEach(key => {
const currentObj = obj[key];
currentPropertyPath = `${previousPath}.${key}`;
if (JSON.stringify(currentObj) === JSON.stringify(queryObject)) console.log(currentPropertyPath); // this is what we are looking for
findPropertyPath(currentObj, currentPropertyPath); // since we are using recursion this is not suited for deeply nested objects
})
}
findPropertyPath(information, "information"); // call the function with the root key
This will find all "property paths" that contain an object that is equal to your query object (compared by value) using recursion.
information.house.city.findMe
information.findMeToo
const contains = (item, data) => item === data || Object.getOwnPropertyNames(data).some(prop => contains(item, data[prop]));
const information = {
city: {
Streetname: ''
}
}
console.log(contains(information.city, information));
console.log(contains({}, information));
How can I pass the subCategory in as an parameter for the function? I have a working solution just passing in the param and then having a switch do the work to make the JSON.subcategory read from the right place. However I feel like there is some thing I am missing on making this more functional, or OO friendly.
So is there a way to make the passed param understand its a variable and not the object literal.
json = {
weather: ["rain", "snow","sun"],
news: ["events", "local","world"]
}
messageBuilder(weather)
function messageBuilder(passedVariable){
var object = json.passedVariable;
// object = json.weather
console.log(JSON.stringify(object));
}
Also am I using the terms correctly? I tried to search google for an answer and ended up not really finding anything.
Just pass the object property key name (sub category) in as a string and use bracket notation to pick it from the data in the function.
Note: that's an object, not JSON, so I've named it as such in the example.
const obj = {
weather: ["rain", "snow", "sun"],
news: ["events", "local", "world"]
};
messageBuilder('weather');
function messageBuilder(subCat){
var object = obj[subCat];
console.log(JSON.stringify(object));
}
Just modify your code a little bit:
json = {
weather : [
"rain", "snow","sun"
],
news : [
"events", "local","world"
]
}
messageBuilder('weather');
function messageBuilder(passedVariable){
var object = json[passedVariable];
// object = json.weather
console.log(object);
}
First of all you should pass your parameter as a string. Then just pull out the property from the object using object['property']