I have data in unordinary format const variations
const variations = {
0: "{"productPriceLocal": "16990.00", "productId": "30028132"}",
1: "{"productPriceLocal": "22990.00", "productId": "30028233"}"
};
// this code doesn't work
// console.log(_.map(variations, 'productId'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
and I want this to convert to normal JS object like this, which with I can normally work
const object = {
0: {
productId: 30028132,
...
},
...
}
I tried to use lodash, doesn't work well. Does Anyone know, what I should do?
The first problem you have is that "{"productPriceLocal": "16990.00", "productId": "30028132"}" includes unescaped quotes that are terminating the string before you want it to (resulting in errors). So if you contain that string with single quotes your first problem should be fixed.
Then parsing the JSON objects as done below should produce the output you are looking for, no lodash nessecary.
const variations = {
0: '{"productPriceLocal": "16990.00", "productId": "30028132"}',
1: '{"productPriceLocal": "22990.00", "productId": "30028233"}'
};
var output = {};
for(key in variations) {
output[key] = JSON.parse(variations[key]);
}
console.log(output);
You could use Array reduce and Object.keys methods to map your object to a single object of the type you're wanting.
//Make sure you escape the quotes in your JSON strings.
const variations = {
0: "{\"productPriceLocal\": \"16990.00\", \"productId\": \"30028132\"}",
1: "{\"productPriceLocal\": \"22990.00\", \"productId\": \"30028233\"}"
};
let parsedValues = Object.keys(variations) // Get keys as an array [0,1]
.reduce((obj, key) => {
// parse to an object.
obj[key] = JSON.parse(variations[key]);
return obj;
}, {} /* initialization object */);
console.log(parsedValues);
Related
Let's say I have two arrays which are returned in a response from a REST call. For simplification I defined them hard-coded as keys and subKeys in the following example code.
From these arrays I'd like to create a nested object which, when outputted as a JSON string, looks like this:
Target JSON
{
"key1": {
"subKey1": "someValue"
},
"key2": {
"subKey2": "someValue"
},
"key3": {
"subKey3": "someValue"
}
}
Code sample
var keys = ["key1", "key2", "key3"]; // These come from a REST response
var subKeys = ["subKey1", "subKey2", "subKey3"]; // These come from a REST response
var targetObj = {}
for (const key in keys) {
targetObj[key] = {}
for (const subKey in subKeys) {
targetObj[key][subKey] = "someValue";
}
}
console.log(JSON.stringify(targetObj, null, 2));
While this gives me the correct behavior in my application I have the impression that there might be simpler approaches to achieve the same result, either in "vanilla" JavaScript or ES6? What bothers me here is that I define an empty object in each run of the for loop.
Your code does not produce the example output you said you want. It will put all 3 subkeys under each key, not one per key. Also you end up with numeric keys, not the key names.
var keys = ["key1", "key2", "key3"]; // These come from a REST response
var subKeys = ["subKey1", "subKey2", "subKey3"]; // These come from a REST response
var targetObj = {}
for (let i=0; i<keys.length; i++) {
const key = keys[i];
targetObj[key] = { [subKeys[i]]: "someValue" };
}
console.log(JSON.stringify(targetObj, null, 2));
First you were using "in" instead of "of" in the for-loop, and secondly you were not using the same index to find the subkey.
To avoid creating an empty object you can use this syntax:
{ [variable]: "value" }
This creates the object with the variable value as the key, and a string as the value. Putting the variable name in square brackets tells it to use the variable value rather than its name. Saying { variable: "value" } wouldn't work because the key would be "variable" not the value of variable.
Just use Array.prototype.reduce method:
const keys = ["key1", "key2", "key3"];
const subKeys = ["subKey1", "subKey2", "subKey3"];
const result = keys.reduce((acc, key, index) =>
({ ...acc, [key]: { [subKeys[index]]: 'someValue' } })
, {});
Note, this works only if keys and subKeys arrays are synced and their indexes are consistent with each other.
I have a json object in a table like below
filter: {where: { AND:[{gender: {IN: "Female"}},{age: {LTE: 44}}]}, relativeDateRange: 90}
which I am fetching and need to change, By removing some of the text.
The new json object will look like below
{"filter": {"where": {"gender": {"IN": "Female"}, "age": {"LTE": 54}},"relativeDateRange": 90}}
One way of doing that is to stringify the object and replacing the keyword,
which in my "theory" should work. however by any mean I am not able to replace ('{"AND":') to blank.
The issue is the keyword contains double inverted comma.
below is the code:
s is the json object which contains the wrong json.
var stringified = JSON.stringify(s);
var t1 = stringified.replace("}{",", ").replace("}}]}","}}").replace('{"AND":', '')
var jsonObject = JSON.parse(t1);
console.log("new json:" +jsonObject);
The text which does not have double inverted comma is getting replaced.
Even using regex or escape character is not helping.
Any suggestion
One option you can try is to use the replacer function which is a parameter in JSON.stringify:
// Your initial filter object
const filter = {filter: {where: { AND:[{gender: {IN: "Female"}},{age: {LTE: 44}}]}, relativeDateRange: 90}};
// Define your replacer function:
const replacer = (name, value) => {
if (name === 'where') {
const array = value['AND'];
// Merge array elements or alter your output in any other way
return Object.assign({}, array[0], array[1]);
}
return value;
}
// The resulting output
console.log(JSON.stringify(filter, replacer, 2));
will produce the following output:
{
"filter": {
"where": {
"gender": {
"IN": "Female"
},
"age": {
"LTE": 44
}
},
"relativeDateRange": 90
}
}
I don't think it's the colon that's throwing off your text replacement statement. How about replacing the "AND" string first, before you complicate it by replacing the curley braces? It should not otherwise effect your other replacements.
var t1 = stringified.replace("AND:[","").replace("}{",", ").replace("}}]}","}}");
The final resolution or more precisely the problem i figure out was,
When a josn is stringified, Its add '\' before every word. As for example when below json is stringified.
filter: {where: { AND:[{gender: {IN: "Female"}},{age: {LTE: 44}}]}, relativeDateRange: 90}
it gives the output as
\filter: {\where: { \AND ....
And the simple resolution was to use replace with double backslash as below.
var t1 = stringified.replace('{\\"AND\\":','').replace(/}{/g,",").replace("}}},","}},").replace('{/"/":','')
Is there a native (built in) in ES6 (or subsequent versions), Javascript or in TypeScript method to convert a JSON string to ES6 map OR a self-made parser to be implemented is the option? The goal is to preserve the order of the keys of the JSON string-encoded object.
Note: I deliberately don't use the word "parse" to avoid converting a JSON string first to ECMA script / JavaScript object which by definition has no order of its keys.
For example:
{"b": "bar", "a": "foo" } // <-- This is how the JSON string looks
I need:
{ b: "bar", a: "foo" } // <-- desired (map version of it)
UPDATE
https://jsbin.com/kiqeneluzi/1/edit?js,console
The only thing that I do differently is to get the keys with regex to maintain the order
let j = "{\"b\": \"bar\", \"a\": \"foo\", \"1\": \"value\"}"
let js = JSON.parse(j)
// Get the keys and maintain the order
let myRegex = /\"([^"]+)":/g;
let keys = []
while ((m = myRegex.exec(j)) !== null) {
keys.push(m[1])
}
// Transform each key to an object
let res = keys.reduce(function (acc, curr) {
acc.push({
[curr]: js[curr]
});
return acc
}, []);
console.log(res)
ORIGINAL
If I understand what you're trying to achieve for option 2. Here's what I came up with.
https://jsbin.com/pocisocoya/1/edit?js,console
let j = "{\"b\": \"bar\", \"a\": \"foo\"}"
let js = JSON.parse(j)
let res = Object.keys(js).reduce(function (acc, curr) {
acc.push({
[curr]: js[curr]
});
return acc
}, []);
console.log(res)
Basically get all the keys of the object, and then reduce it. What the reducer function convert each keys to an object
function jsonToMap(jsonStr) {
return new Map(JSON.parse(jsonStr));
}
More details : http://2ality.com/2015/08/es6-map-json.html
use for in loop
let map = new Map();
let jsonObj = {a:'a',b:'b',c:'c'}
for (let i in jsonObj){
map.set(i,jsonObj[i]);
}
btw, i saw the comment below and i think map is not ordered because you use key to achieve data in map, not the index.
is there a "Nice" way to get all the values out of a json object (I don't care about the keys) - just get the values into array,
without using a loop ?
(lang is Javascript)
It depends on how you define "loop".
You can extract the properties with Object.keys and then map them to their values.
… it's still essentially a loop under the hood though.
var json = `{ "foo": 1, "bar": 2, "baz": 3 }`;
var obj = JSON.parse(json);
var values = Object.keys(obj).map(function (key) { return obj[key]; });
console.log(values);
With weaker browser support you could use the values method.
var json = `{ "foo": 1, "bar": 2, "baz": 3 }`;
var obj = JSON.parse(json);
var values = Object.values(obj);
console.log(values);
I think you are looking for Object.values() function, just pass the object to the values method of Object as first param. That's it!
Object.values({something: 'lol'});
> ["lol"]
Recursively extract as text
Yes, this is a loop but the underlying methods you are calling such as Object.values or arr.map are still loops. I found this useful for extracting text out of a json object for full text search in particular and thought it useful as I came here initially needing this but the answers only touched the surface as json is recursive in nature.
function textFromJson(json) {
if (json === null || json === undefined) {
return '';
}
if (!Array.isArray(json) && !Object.getPrototypeOf(json).isPrototypeOf(Object)) {
return '' + json;
}
const obj = {};
for (const key of Object.keys(json)) {
obj[key] = textFromJson(json[key]);
}
return Object.values(obj).join(' ');
}
With ES2017 you have Object.values(). You can polyfill it also.
Only you need is transform JSON to JavaScript object and call Object.values(). The result is an array of values.
var obj = JSON.parse(jsonData);
var result = Object.values(obj);
If you pass a function to JSON.parse, it will be called each time a value is parsed:
function get_values(json) {
let values = []
JSON.parse(json, (key,value)=>{ values.push(value) })
return values
}
ex:
get_values(`{"a":1, "b":[true, false], "c":3}`)
// returns a list of:
• 1
• true
• false
• [true, false]
• 3
• {a:1, b:[true, false], c:3}
Note: If you don't consider the full object to be a "value", just remove the last item.
That so crazy, but I'm trying to convert a JSON to a JSON for any reason.I have json and i checked json at http://jsonlint.com, it's ok.
{"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"ID\":\"VN00000456\",\"NAME\":\"MERRY BLUE\",\"GENDER\":\"Female\",\"BIRTHDAY\":\"03-12-1983\"},{\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"09-07-1990\"}]"}
Now, what I need convert it like this at the following
{
"columns": [
["ID"],
["NAME"],
["GENDER"],
["BIRTHDAY"]
],
"data": [
[
"VN00000123",
"JOHN GREEN",
"Male",
"15-10-1987"
],
[
"VN00000456",
"MERRY BLUE",
"Female",
"03-12-1983"
],
[
"VN00000789",
"BLACK BROWN",
"Male",
"09-07-1990"
]
]
}
Somebody've ideas for this, share with me (using javascript or jquery). Thank you so much.
This algorithm is pretty straightforward--something like the following should work:
function parse(a) {
//create object to return
var ret = {
columns: [],
data: []
};
//iterate the source array
a.forEach(function(item, i) {
if (i === 0) {
//first time through, build the columns
for (var key in item) {
ret.columns.push(key);
}
}
//now build your data item
ret.data[i] = [];
//use the column array to guarantee that the order of the fields in the source string doesn't matter
for (var j = 0; j < ret.columns.length; j++) {
var key = ret.columns[j];
ret.data[i].push(item[key]);
}
});
return ret;
}
var j = {
"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"NAME\":\"MERRY BLUE\",\"BIRTHDAY\":\"03-12-1983\",\"ID\":\"VN00000456\",\"GENDER\":\"Female\"},{\"GENDER\":\"Male\",\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"BIRTHDAY\":\"09-07-1990\"}]"
};
//j is an object with one property (d) that is a JSON string that needs parsing
var o = parse(JSON.parse(j.d));
console.log(o);
You can try this example using jQuery:
https://jsfiddle.net/de02fpha/
var dump = {"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"ID\":\"VN00000456\",\"NAME\":\"MERRY BLUE\",\"GENDER\":\"Female\",\"BIRTHDAY\":\"03-12-1983\"},{\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"09-07-1990\"}]"};
var parse = function(json) {
var columns = [];
var data = [];
$.each(json, function(index, row) {
var element = [];
for (var key in row) {
if (columns.indexOf(key) == -1) columns.push(key);
element.push(row[key]);
}
data.push(element);
});
return {columns: columns, data: data};
};
var json = $.parseJSON(dump.d);
console.log(parse(json));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
In javascript, the built in JSON class provides the two tools you need to format your JSON, no need for jquery:
JSON.parse() will handle parsing the text, and JSON.stringify can handle taking our parsed JSON and turning into a nice pretty string.
Let's slap them together.
Start with parsing and storing the JSON:
var parsedData = JSON.parse(dataToFormat);
Now to print our parsed data, we need to learn a little bit about the stringify function, specifically its space argument. Per MDN:
JSON.stringify(value[, replacer[, space]])
The space argument may be used to control spacing in the final string. If it is a number, successive levels in the stringification will each be indented by this many space characters (up to 10). If it is a string, successive levels will be indented by this string (or the first ten characters of it).
JSON.stringify({ uno: 1, dos: 2 }, null, '\t');
// returns the string:
// '{
// "uno": 1,
// "dos": 2
// }'
Note that the above code sample uses the tab character, but as described in the doc you can simply insert a number and it will use that number of spaces instead.
Alright let's print
var prettyData = JSON.stringify(parsedData, null, '\t');
prettyData should now contain a neatly formatted and indented string.
You can throw this into one line if you'd like:
var prettyData = JSON.stringify(JSON.parse(dataToFormat),null,'\t');
Now, if you wanted to add a key or something to the very top of the JSON object, you could simply define some kind of key object and attach it to the object you pass in to JSON.stringify. JSON.parse gives you a standard object, so modify it like you would any other.